Skip to content

Make Generate deterministic and add CI verification step#89

Open
jaredpar wants to merge 5 commits into
mainfrom
jaredpar/deterministic-file-enumeration
Open

Make Generate deterministic and add CI verification step#89
jaredpar wants to merge 5 commits into
mainfrom
jaredpar/deterministic-file-enumeration

Conversation

@jaredpar

Copy link
Copy Markdown
Owner

The Generate tool's output was non-deterministic because Directory.GetFiles does not guarantee enumeration order, and different OSes return files in different orders. This meant running the generator on Linux vs Windows could produce different Generated.cs/targets files even with identical inputs.

Approach

  • In FindDlls, collect results into a list instead of yielding immediately, normalize path separators to /, and sort by relative path using StringComparison.Ordinal. This ensures identical output regardless of OS or filesystem behavior.
  • Rebaselined all 53 generated files with the new deterministic ordering.
  • Added a CI workflow step that runs the generator after restore and fails if there is any diff, ensuring PRs always ship freshly generated output.

jaredpar and others added 5 commits June 12, 2026 09:44
The file system enumeration in FindDlls was non-deterministic because
Directory.GetFiles does not guarantee ordering, and the ordering varies
across operating systems. Fix by:

1. Collecting all results into a list instead of yielding immediately
2. Normalizing path separators to forward slash for consistent sorting
3. Sorting by relative path using ordinal comparison

This ensures the generated output is identical regardless of OS or
file system enumeration order.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Runs the generator after restore and fails the build if there are any
uncommitted diffs, ensuring PRs always include freshly generated output.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Path.Join uses the OS-specific separator between the prefix and the
relative path, producing different output on Windows vs Linux. Replace
with string interpolation using a consistent forward slash separator
since MSBuild handles both styles.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
On Linux, Substring(packagePrefix.Length) produces a leading / in the
relative path. Combined with the interpolated /, this caused // in the
output. TrimStart('/') after normalization ensures no leading separator.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add .gitattributes to enforce LF line endings and normalize the
generator output with ReplaceLineEndings to always produce LF.
This ensures the generator produces identical output on Windows
and Linux, making the CI verification step pass on both platforms.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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