fix: enforce LF line endings for shell scripts, gradlew, KEYS#15622
Open
jamesfredley wants to merge 1 commit into7.0.xfrom
Open
fix: enforce LF line endings for shell scripts, gradlew, KEYS#15622jamesfredley wants to merge 1 commit into7.0.xfrom
jamesfredley wants to merge 1 commit into7.0.xfrom
Conversation
The release verification flow runs in a Linux container built from etc/bin/Dockerfile, but the repository had no .gitattributes. With Git for Windows' default core.autocrlf=true, every Windows checkout converts gradlew, etc/bin/*.sh, the Dockerfile, and the KEYS file from LF to CRLF in the working tree. The Dockerfile's ADD then preserves those CRLFs into the image, with three failure modes: 1. The Linux kernel refuses to execute scripts with `bash\r` in the shebang, so gradlew and every verify-*.sh script fails with `cannot execute: required file not found`. 2. verify-keys.sh hashes the in-tree KEYS file and compares against https://dist.apache.org/repos/dist/release/grails/KEYS, which is stored as LF. The hashes mismatch even though the content is byte-identical after line-ending normalization. 3. By extension, verify.sh aborts at its first step on any Windows committer's machine. Fix at the right layer (git's working-tree write path): - Add .gitattributes pinning *.sh, gradlew, KEYS, Dockerfile, and *.properties to eol=lf, while keeping *.bat / *.cmd / gradlew.bat as eol=crlf and marking common binary types as binary so git never tries to normalize them. Default `* text=auto` lets git auto-detect everything else. - Add a defensive sed-strip step in etc/bin/Dockerfile after the ADD lines, so even if a committer feeds a CRLF-corrupted build context (existing local checkout under autocrlf=true), the image still ends up with LF scripts. Existing index content is unchanged: every affected file is already stored as LF in the index. This commit only changes what `git checkout` writes to the working tree on Windows and adds belt-and- braces normalization at image-build time. CI on ubuntu-latest is unaffected. Linux/macOS verifiers are unaffected. Windows verifiers can now run the container build flow documented in RELEASE.md without manual workarounds. This is the 7.0.x companion to #15620 (against 8.0.x). The line-ending bug exists identically on 7.0.x because the Dockerfile and verify-*.sh scripts are the same byte-for-byte. Assisted-by: claude-code:claude-opus-4-7
✅ All tests passed ✅🏷️ Commit: 86410d0 Learn more about TestLens at testlens.app. |
jdaugherty
approved these changes
May 3, 2026
Contributor
jdaugherty
left a comment
There was a problem hiding this comment.
The dockerfile change appears to be windows specific, but we want our environments to function the same so I'm approving.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
7.0.x companion to #15620. Pin the line endings of shell scripts,
gradlew,KEYS, and the Dockerfile to LF on every platform, and add a defensivesedstrip step inetc/bin/Dockerfile, so the release verification container is reproducible from a Windows committer's checkout.Why
There is no
.gitattributesin the repo today. With Git for Windows' defaultcore.autocrlf=true, every Windows checkout converts these files from LF to CRLF in the working tree. The Dockerfile'sADDthen preserves the CRLF into the image, which produces three independent failures during release verification:bash\rin the shebang, sogradlewand everyverify-*.shscript fail withcannot execute: required file not found//usr/bin/env: 'bash\r': No such file or directory.verify-keys.shshasum-512s the in-treeKEYSfile and compares against the canonical copy athttps://dist.apache.org/repos/dist/release/grails/KEYS. The two byte-streams differ by exactly one\rper line (52 bytes total) and the comparison fails even though the content is byte-identical after normalization.verify.shaborts at its first step (verify-keys.sh) on any Windows committer's machine. The container documented inRELEASE.mdis unusable as-is.CI on
ubuntu-latestand any Linux/macOS verifier are unaffected. The bug is only visible to a Windows committer because git's checkout-time conversion is the layer that introduces the corruption.The line-ending bug exists identically on 7.0.x:
etc/bin/Dockerfileand theverify-*.shscripts are byte-for-byte the same as on 8.0.x (the only Dockerfile delta between branches is the JDK version -17.0.18here vs21.0.7on 8.0.x), and 7.0.x has the same identical missing-.gitattributessituation.Why fix this at the
.gitattributeslayer.gitattributesis the only mechanism in the repo that operates at git's working-tree write path. Other code-style mechanisms either don't run at the right time or don't cover the right files:*.sh/gradlew/KEYS?.editorconfig(existing - groovy/java only)codeStyletask.gitattributes(this PR)Changes
.gitattributes(new)* text=auto- sane default; git auto-detects text vs binary, stores text as LF in the index*.sh,gradlew,KEYS,Dockerfile,*.properties->text eol=lf(must be LF on Linux verifier and CI)*.bat,*.cmd,gradlew.bat->text eol=crlf(must be CRLF on Windows)*.jar,*.zip,*.png,*.pdf,*.gpg,*.keystore, ...) markedbinaryso git never normalizes themetc/bin/DockerfileAdd a
RUN sed -i 's/\r$//'step after theADDlines, scoped to*.sh,gradlew,KEYS, and*.properties. This is belt-and-braces: even if a committer's working tree still has CRLF (because their local checkout predates this PR and they have not re-checked-out / renormalized), the image they build will still be correct.Index impact
Verified ahead of time on the 7.0.x worktree:
$ git ls-files --eol gradlew etc/bin/verify.sh KEYS gradlew.bat etc/bin/Dockerfile i/lf w/lf attr/text eol=lf KEYS i/lf w/lf attr/text eol=lf etc/bin/Dockerfile i/lf w/lf attr/text eol=lf etc/bin/verify.sh i/lf w/lf attr/text eol=lf gradlew i/crlf w/crlf attr/text eol=crlf gradlew.batEvery affected file is already LF in the index. This PR therefore does not require
git add --renormalize .and does not produce any blob churn - it only changes whatgit checkoutwrites to disk on the next checkout, and pins the contract going forward.Related
8.0.x).With both PRs merged, the container verification flow is reproducible on every platform for both the 7.0.x maintenance line and the 8.0.x development line.