Repository navigation
Conversation
|
A label of 'needs-attention' was automatically added to this PR in order to raise the |
…providers.exec build.gradle opened the repository with JGit at configuration time to compute the commit id and the RAT excludes. With the configuration cache enabled, Git.open starts external processes (`git --version`, `git config --system ...`) that Gradle cannot track, so it reports configuration cache problems and fails the build by default. Use providers.exec to run `git rev-parse HEAD` and `git ls-files --others --directory` instead. Gradle tracks their output as configuration inputs, so a new commit or a new untracked file correctly invalidates the cache. The RAT exclude set is unchanged: on a working tree, JGit's clean().setDryRun(true) output matches `git ls-files --others --directory` exactly. This also removes an implicit dependency: since KAFKA-21086 the org.eclipse.jgit import in build.gradle relied on JGit being on the build script classpath transitively via the Spotless plugin (:generator keeps its own JGit dependency). .git is now checked with exists() instead of isDirectory(), so builds in a git worktree (where .git is a file) also get the real commit id and run RAT. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moving build.gradle from JGit to the git CLI made the build depend on how git formats its output, on git's environment and on a working git command. This fixes the resulting regressions. Changes: - Read `git ls-files` with -z and split on NUL. Without -z, git quotes and escapes names with non-ASCII characters or double quotes, so those RAT excludes matched nothing and RAT could fail on an untracked file. - Run git with --git-dir=.git --work-tree=. so that it reads the root directory's own repository. This overrides GIT_DIR and GIT_WORK_TREE, stops the search through parent directories and still works in git worktrees. Previously, a GIT_DIR pointing to another repository silently gave that repository's commit id and made RAT exclude almost every file. - Read HEAD once during configuration. If git cannot read it, log a warning with the reason and handle the tree like a source tarball: the commit id is `unknown` and RAT is disabled. isGitCheckout is now true only when HEAD can be read. Decisions: - Fall back rather than fail, so that builds keep working without a usable git, for example in a JDK-only container. The cost is that a broken git skips RAT with only a warning. - Use explicit git paths rather than removing variables from the environment: removing them through the providers.exec environment had no effect when tested. - An explicit --git-dir skips git's safe.directory check. Gradle already runs that checkout's build script, so this adds no meaningful risk. - Keep git's own message in the warning, although reading it takes a few more lines. Commit id and RAT in each .git state: - Normal clone, git worktree, -PcommitId, GIT_DIR set: the expected commit id, RAT active. - Dubious ownership, simulated with GIT_TEST_ASSUME_DIFFERENT_OWNER: the real commit id, RAT active. - No .git, also inside a parent repository: `unknown`, RAT skipped, no warning. - Dangling .git file, empty .git directory (also inside a parent repository), no commits yet, git not installed: `unknown`, RAT skipped, with a warning. RAT, compared with JGit on the same tree: - Clean tree, and untracked non-ASCII names, double quotes, spaces, empty and untracked directories, a file in a tracked directory, ignored files: same report apart from the timestamp. The excludes were also compared directly on a tree with the non-ASCII and double quote names, and were identical and in the same order. - Untracked nested git repository (without commits): RAT now passes because the directory is excluded. JGit scanned its files and failed. Distribution: comparing a clean releaseTarGz with the JGit build gave the same 225 files. Jar entries differ only in the commitId of the 9 jars with a version file, jar entry timestamps also differ, and the site-docs contents are identical. Configuration cache: the entry is reused when nothing changed and after an unrelated environment variable, GIT_DIR, a new ref or git gc. A new commit or a change in untracked files invalidates it. Known limitations: - With the configuration cache enabled and git not installed, the build fails, because Gradle reports the process that could not start as a configuration cache problem. This branch does not enable the cache. - A backslash in an untracked name fails RAT with `Cannot read header`, as it did with JGit. - With LC_ALL=C on JDK 25, a non-ASCII untracked name fails with FileNotFoundException, while JGit passes. LC_ALL=C on JDK 17 passes. These locale checks ran on the -z change, before the rest of this commit was added. - GIT_INDEX_FILE is still respected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
451744e to
f0c2c21
Compare
build.gradle used JGit at configuration time to compute the commit id and the RAT excludes. Git.open starts external processes (`git --version` and `git config --system`) that the configuration cache reports as problems, which is one of the things preventing the cache from being enabled. This change does not enable it. It also removes the script's implicit dependency on the JGit jar that the Spotless plugin brings in. build.gradle now runs `git rev-parse HEAD` and `git ls-files -z --others --directory` through providers.exec, so that Gradle tracks their output as configuration inputs. Git runs with --git-dir=.git --work-tree=. so that it always reads the root directory's own repository. Behaviour changes: - In a git worktree, the build now gets the real commit id and runs RAT, instead of using `unknown` and skipping RAT. - If git cannot read HEAD, for example because it is not installed, the build logs a warning, uses `unknown` and skips RAT, as it does for a source tarball. Some of these cases used to fail the build, and a missing git used to work with JGit. - An untracked nested git repository is now excluded from RAT. The Kafka distribution content is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
f0c2c21 to
fd4fad7
Compare
Testing notesTests were run in a session with Claude, on throwaway clones, using Linux, Gradle 9.8.2, git 2.43.0 and JDK 25 (plus JDK 17 where noted). The baseline is trunk RATUntracked entries depend on the tree state when Gradle configures the build, so each comparison needs the same tree state. For example, run the first commit twice and compare its second run.
"Same report" means identical apart from the timestamp. On a tree with the non-ASCII and Commit id and RAT by
|
| State | JGit | This PR |
|---|---|---|
| Normal clone | real id, RAT active | same |
-PcommitId=... |
given value, RAT active | same |
No .git, also inside a parent repository |
unknown, RAT skipped |
same |
| Git worktree | unknown, RAT skipped |
real id, RAT active |
GIT_DIR set to another repository |
real id, RAT active | same |
Dubious ownership (simulated with GIT_TEST_ASSUME_DIFFERENT_OWNER) |
real id, RAT active | same |
| git not installed | real id, RAT active | unknown, RAT skipped, warning |
Dangling .git file |
unknown, RAT skipped |
unknown, RAT skipped, warning |
Empty .git directory |
build fails | unknown, RAT skipped, warning |
git init without commits |
build fails | unknown, RAT skipped, warning |
Empty .git directory inside a parent repository |
not tested | unknown, RAT skipped, warning |
Distribution
Compared a clean releaseTarGz from the baseline and the final code:
- Both have the same 225 files.
- Jar entries differ only in
commitId, in the 9 jars with a version file. Jar entry timestamps also differ. - The 196 site-docs files have identical contents.
kafka-transactions.sh --versionprints the expected commit id.
Configuration cache
Checked with --configuration-cache rat only. This PR does not enable the cache, and the build still fails with it enabled on other task graphs.
| Change between runs | Cache entry |
|---|---|
None, an unrelated environment variable, GIT_DIR, a new ref, git gc |
reused |
| New commit, added or removed untracked file | invalidated |
| git not installed | build fails with a configuration cache problem, even with the fallback |
Known gaps
- With
LC_ALL=C, a non-ASCII untracked name passes on JDK 17 but fails on JDK 25 withFileNotFoundException, while JGit passes on both. This ran on the-zchange, before the--git-dirand fallback code, and was not rerun. - Without the temporary
doLastblock, onlyclients:createVersionFile ratwas rerun, and it passed. GIT_INDEX_FILEis still respected by git.
|
➡️ This PR is ready for review, but please review #23424 (RAT upgrade) first. Both PRs change the same Once #23424 is merged, I will:
Small note for this PR: last commit is empty (it serves as a placeholder for the final commit message). |
Notes:
which blocks upgrade to Gradle 10: KAFKA-20102 Preparations for Gradle 10update: see this jira commentrequires more manual (human) testing; testing steps will be added ASAPadditional testing has been performed, see testing comment belowDrafted with Claude, then reviewed and edited.
❌ Pitfall:
build.gradleopens the repository with JGit at configuration time to compute thecommit idand theRAT excludes.Git.openstarts external processes (git --version,git config --system ...) that Gradle cannot track, so it reports configuration cache problems and fails the build by default.💡 Solution:
build.gradlenow runsgit rev-parse HEADandgit ls-files -z --others --directorythroughproviders.exec, so Gradle tracks their output as configuration inputs. A new commit or a change in untracked files invalidates the cache.--git-dir=.git --work-tree=., so it always reads the root directory's own repository, regardless ofGIT_DIRor a repository in a parent directory. This also skips git'ssafe.directorycheck, but Gradle is already running that checkout's build script.Behaviour changes:
unknownand skipping RAT.HEAD, for example because it is not installed, the build logs a warning, usesunknownand skips RAT, as it does for a source tarball. With JGit, a missing git still gave the real commit id and ran RAT, while cases such as an empty.gitdirectory failed the build.The contents of the Kafka distribution are unchanged.
This also removes an implicit dependency: since KAFKA-21086 the
org.eclipse.jgitimport inbuild.gradlerelied on JGit being on the build script classpath transitively via the Spotless plugin; related PR ⬇️Note:
:generatorsubmodule keeps its own JGit dependency (fetched fromgradle/dependencies.gradle).Co-Authored-By: Claude Opus 5.5 noreply@anthropic.com