Skip to content

fix(backend): emit LF-only OpenAPI spec to avoid phantom Windows CRLF diffs - #1503

Merged
Junirezz merged 1 commit into
Junirezz:mainfrom
simonpeters298:chore/1374-fix-crlf-normalization
Oct 2, 2026
Merged

Junirezz merged 1 commit into
Junirezz:mainfrom
simonpeters298:chore/1374-fix-crlf-normalization

Conversation

@simonpeters298

Copy link
Copy Markdown
Contributor

Closes #1374

Problem

backend/openapi.json is reported as modified (M) after npm run generate:openapi on Windows even though the file is byte-identical to HEAD — only CRLF/LF normalization differs. This produces phantom working-tree changes that make it hard to tell whether the spec actually drifted.

Root cause

backend/scripts/generate-openapi.ts preserved whatever line ending the existing output file happened to have:

const eol = fs.existsSync(outputPath) && fs.readFileSync(outputPath, 'utf8').includes('\r\n') ? '\r\n' : '\n';
fs.writeFileSync(outputPath, content.replace(/\n/g, eol), 'utf8');

Once openapi.json had CRLF in the working tree (a Windows editor, or a legacy checkout from before .gitattributes existed), every regeneration rewrote it as CRLF. Git then flagged the file as modified while the diff was empty:

CRLF working copy : " M backend/openapi.json"   (git diff -> 0 lines)
LF   working copy : clean

Fix

  1. backend/scripts/generate-openapi.ts — always write LF. Output is now platform-independent and matches the repository's .gitattributes (* text=auto eol=lf). Removed the now-unused os import.
  2. .gitattributes — pin generated artifacts with an explicit text eol=lf (backend/openapi.json, backend/schema-snapshots/*.json, docs/schemas/webhooks/*.json) so they are always treated as text and checked out as LF.
  3. scripts/validate-generated-artifacts.ts + test — new guard that fails if any committed generated artifact contains CRLF. Wired as pnpm validate:line-endings / pnpm test:validate-line-endings.

Verification

  • vitest run scripts/validate-generated-artifacts.test.ts -> 4/4 passing (8/8 together with the existing image-size tests).
  • git check-attr now reports text: set / eol: lf for the generated artifacts.
  • backend/openapi.json itself is unchanged — it was already LF, so there is zero artifact churn.
  • The phantom-diff condition is reproduced and confirmed resolved: a CRLF working copy shows M with an empty diff, whereas an LF working copy is clean, and the generator now always writes LF.

Notes

  • Only generate-openapi.ts had the EOL-preserving heuristic; the schema-snapshot and webhook JSON-schema generators already write LF.
  • This addresses line endings introduced or kept by regeneration. If an editor introduces CRLF between runs, git add --renormalize remains the escape hatch, which is inherent Git behavior.

generate:openapi preserved the EOL already present in backend/openapi.json,
so on Windows a CRLF working copy was re-written as CRLF. Regeneration then
left the file flagged as modified while `git diff` was empty — a phantom
change caused purely by CRLF/LF normalization.

Always write LF, pin generated artifacts to `text eol=lf` in .gitattributes,
and add a validator + test that fails on CRLF in generated artifacts.

Closes Junirezz#1374
@drips-wave

drips-wave Bot commented Sep 29, 2026

Copy link
Copy Markdown

@simonpeters298 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Junirezz
Junirezz merged commit aaeb012 into Junirezz:main Oct 2, 2026
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.

Generated artifacts flagged as modified on Windows due to CRLF normalization noise

2 participants