Lint for filename case collisions and enforce lowercase on new assets#4145
Draft
dannon wants to merge 1 commit into
Draft
Lint for filename case collisions and enforce lowercase on new assets#4145dannon wants to merge 1 commit into
dannon wants to merge 1 commit into
Conversation
Adds check-filename-case.mjs to the content:lint pipeline. It fails on any two tracked paths that differ only in case -- the Keynote.jpg/keynote.jpg problem that's bitten us twice, which collides on macOS and Windows and leaves git reporting a phantom modification. It also fails on newly added image/media assets with uppercase names, while leaving the ~1600 existing uppercase files alone (the new-asset check only looks at files added relative to the PR base). Because that diff needs the base, the content-lint job now fetches full history and passes the base SHA. Includes unit tests and a CONTRIBUTING note.
itisAliRH
reviewed
Jul 24, 2026
itisAliRH
left a comment
Member
There was a problem hiding this comment.
Reviewed early since it's a draft; nice idea, and grandfathering old files is the right call. Two spots where the lint passes when it shouldn't:
Renames slip past. listAddedFiles uses git diff --diff-filter=A, and git detects renames by default, so git mv keynote.jpg Keynote.jpg shows up as R, not A. That's a likely way this bug comes back.
git(['diff', '--no-renames', '--diff-filter=A', '--name-only', '-z', base])The CLI guard can quietly do nothing.
if (import.meta.url === `file://${process.argv[1]}`) {import.meta.url is percent-encoded, so if the checkout path has a space or a non-ASCII character, this is false, main() never runs, and the script exits 0 with no output. CI goes green having checked nothing.
import { pathToFileURL } from 'url';
if (import.meta.url === pathToFileURL(process.argv[1]).href) {Smaller notes:
base.shais the base tip from the last sync, not the merge-base. An uppercase file merged to main after that point can get blamed on this PR. Rare, but confusing.fetch-depth: 0pulls every image blob on each lint run. A shallow checkout plusgit fetch --depth=1 origin <base.sha>gets the same thing cheaper./[A-Z]/misses accented capitals likeÄ.jpg;/\p{Lu}/uif you want it tight.
Rest looks good — exit codes, messages, and helper tests all line up with the other lints.
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.
Follow-up to #4143. That was the second time a case-only filename collision (
Keynote.jpgvskeynote.jpg) slipped in, so this adds a lint to catch the class of problem going forward.check-filename-case.mjsjoins thecontent:lintpipeline with two checks:Includes unit tests and a CONTRIBUTING note. I deliberately didn't try to enforce lowercase on all existing files -- that's a much bigger change and a separate discussion if we want it.