From 0a7b02a63c27b7682af459a765223b60a3021475 Mon Sep 17 00:00:00 2001 From: BRUNER Patrick Date: Tue, 28 Jul 2026 09:35:46 +0200 Subject: [PATCH] fix: make plugin hashes reproducible so the fork-PR verify gate can pass The `Verify Plugin Hashes (fork PRs)` step in build_dotnet.yml regenerates PluginHashGenerator.Generated.cs and runs `git diff --exit-code` on it. That gate could never pass, for two independent reasons. First, the generator embedded `DateTime.UtcNow` in the file, so every regeneration produced a diff even when no hash had changed. Second, the SDK queries git and feeds the commit sha into every assembly by two routes: appended to InformationalVersion, and into the SourceLink map in the portable PDB, whose checksum is embedded in the DLL. So the hashes you commit describe the parent commit's binaries and go stale the instant they land - committing them changes HEAD, which changes the binaries again. Only first-party assemblies moved; the NuGet-supplied DLLs alongside them never did. That made the gate unwinnable rather than merely awkward: PR #673 burned two attempts re-pasting hashes, and every push produced a different set again. On Development the same churn was absorbed by the sibling auto-commit step, which is why `chore: update plugin hashes [skip ci]` landed after nearly every merge. It also meant the committed table always described a different build than the one it shipped in, so Release plugin verification never matched its own binaries. Drop the timestamp, stop the SDK's source-control queries, and regenerate. Verified: two clean Release builds at different commits now produce identical plugin hashes, and `git diff --exit-code` on the generated file is clean. --- src/Directory.Build.props | 6 ++++ src/PluginHashGenerator.Tool/Program.cs | 5 ++- .../PluginHashGenerator.Generated.cs | 33 ++++++++++--------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 5fc5b6a22..37331af25 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -4,6 +4,12 @@ 1.40.4.0 1.40.4.0 1.40.4.0 + + false Hirogen, zarunbal, RandallFlagg, TheNicker LogExperts enable diff --git a/src/PluginHashGenerator.Tool/Program.cs b/src/PluginHashGenerator.Tool/Program.cs index bb6765b91..e1ba383d7 100644 --- a/src/PluginHashGenerator.Tool/Program.cs +++ b/src/PluginHashGenerator.Tool/Program.cs @@ -142,8 +142,6 @@ private static int Main (string[] args) private static string GenerateSourceCode (Dictionary pluginHashes, string configuration) { - var timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); - var sb = new StringBuilder(); foreach (var kvp in pluginHashes.OrderBy(kvp => kvp.Key)) @@ -166,7 +164,8 @@ public static partial class PluginValidator { /// /// Gets pre-calculated SHA256 hashes for built-in plugins. - /// Generated: {{timestamp}} UTC + /// Deliberately carries no generation timestamp: the file is committed, and a + /// timestamp would make every regeneration a diff even when no hash changed. /// Configuration: {{configuration}} /// Plugin count: {{pluginHashes.Count}} /// diff --git a/src/PluginRegistry/PluginHashGenerator.Generated.cs b/src/PluginRegistry/PluginHashGenerator.Generated.cs index 579532ac4..dc4c45df8 100644 --- a/src/PluginRegistry/PluginHashGenerator.Generated.cs +++ b/src/PluginRegistry/PluginHashGenerator.Generated.cs @@ -10,7 +10,8 @@ public static partial class PluginValidator { /// /// Gets pre-calculated SHA256 hashes for built-in plugins. - /// Generated: 2026-07-27 12:56:30 UTC + /// Deliberately carries no generation timestamp: the file is committed, and a + /// timestamp would make every regeneration a diff even when no hash changed. /// Configuration: Release /// Plugin count: 21 /// @@ -18,27 +19,27 @@ public static Dictionary GetBuiltInPluginHashes() { return new Dictionary(StringComparer.OrdinalIgnoreCase) { - ["AutoColumnizer.dll"] = "D5EDCF3697201E538F53A907A6D666BC58CF0CD5764497ED3970647810541258", + ["AutoColumnizer.dll"] = "37F64E2C357B933DF31CB6963CAB992A7A868D5E3CBEFE02F86E92E3CB3A31AF", ["BouncyCastle.Cryptography.dll"] = "E5EEAF6D263C493619982FD3638E6135077311D08C961E1FE128F9107D29EBC6", ["BouncyCastle.Cryptography.dll (x86)"] = "E5EEAF6D263C493619982FD3638E6135077311D08C961E1FE128F9107D29EBC6", - ["CsvColumnizer.dll"] = "2AF71FBA774BA1903F2EDDBB95F9647F29D1B9684F0BF843AC01EB304284DD93", - ["CsvColumnizer.dll (x86)"] = "2AF71FBA774BA1903F2EDDBB95F9647F29D1B9684F0BF843AC01EB304284DD93", - ["DefaultPlugins.dll"] = "F1E7C0A1EF18C7D608907B1F61021A3D0F4B21FE8CB4F647E4A1DF950CEA76C5", - ["FlashIconHighlighter.dll"] = "1B34E0910E8D8AEE10925E9B1E8B634B35424B9FD947F7C8B2E9FFAC57C81D77", - ["GlassfishColumnizer.dll"] = "718FE4BEE8C937D93A1291B583F71069263E00AB5F9BA91215324EA04FD8079F", - ["JsonColumnizer.dll"] = "86BFF50430BE0FB03C2E2060D5E3231612632602CC7AD3215815A99EEF63911B", - ["JsonCompactColumnizer.dll"] = "9D3656B14034F091AF19FBD15CF3242322877E9C576A5E7D1A4A7F9EE7E4F34D", - ["Log4jXmlColumnizer.dll"] = "83F86425CB48AEFD64B2B407C007984568A81D76A682AD1DB35A1973A6DF8BFE", - ["LogExpert.Resources.dll"] = "67D1FDA59B2705E688AF66B8CE93C00B41C6DE4E419A8EAD2ADC0109E8CC3DD7", + ["CsvColumnizer.dll"] = "C01B98A49861622BA06316E975EED7F486E3BF0B760A0FC5B0800E7411608A23", + ["CsvColumnizer.dll (x86)"] = "C01B98A49861622BA06316E975EED7F486E3BF0B760A0FC5B0800E7411608A23", + ["DefaultPlugins.dll"] = "9393AF0FC4FB6A88975574C078DFD35454122623059DA908932ABE64892FBA56", + ["FlashIconHighlighter.dll"] = "2C2D76778E0A2AE0A543A0078C6E3A10A3F18C0519E268D724AA73446E678560", + ["GlassfishColumnizer.dll"] = "FADE6EAF3FE3FA760CB35C8F1B044ED37D96D690B8CD19180A6C3F4BEA0CF96B", + ["JsonColumnizer.dll"] = "8E6172B14780EAE85BBB54DB386B2B554283AADDBD6BEBED7EF5472688DB8AA6", + ["JsonCompactColumnizer.dll"] = "DAECABFCCDCE842523C9BDA2A811F099FE9ECF69B2D1FACA39448253076CD8F3", + ["Log4jXmlColumnizer.dll"] = "323E2B3778AFAA787E99025E6A2190B2CF8A939D42394F0300C477F4BABF4160", + ["LogExpert.Resources.dll"] = "8BB318D68ED5BDD7159937CFCFA0E8F70D657BEE3665194F7C1010C6ED6EB8F6", ["Microsoft.Extensions.DependencyInjection.Abstractions.dll"] = "67FA4325000DB017DC0C35829B416F024F042D24EFB868BCF17A895EE6500A93", ["Microsoft.Extensions.DependencyInjection.Abstractions.dll (x86)"] = "67FA4325000DB017DC0C35829B416F024F042D24EFB868BCF17A895EE6500A93", ["Microsoft.Extensions.Logging.Abstractions.dll"] = "BB853130F5AFAF335BE7858D661F8212EC653835100F5A4E3AA2C66A4D4F685D", ["Microsoft.Extensions.Logging.Abstractions.dll (x86)"] = "BB853130F5AFAF335BE7858D661F8212EC653835100F5A4E3AA2C66A4D4F685D", - ["RegexColumnizer.dll"] = "8DFD20115295AD714B1647E480D05DCEC0E7BD97EFF5890F32B9B46E6316BD43", - ["SftpFileSystem.dll"] = "14708AC11BEE347EECD599DA90A92CD27A239E2B52E5A4ED7AB8F01778E8E9F3", - ["SftpFileSystem.dll (x86)"] = "14D0725C05267A5E9BDB685CB60011809D487DDD23FE21A5D13727A3BE1A85C9", - ["SftpFileSystem.Resources.dll"] = "66272F6E94D8B4F4F2BCF216F622370832338926E7F5FFD665F79F161CA3FB0C", - ["SftpFileSystem.Resources.dll (x86)"] = "66272F6E94D8B4F4F2BCF216F622370832338926E7F5FFD665F79F161CA3FB0C", + ["RegexColumnizer.dll"] = "81B19AA71A84902216F1699E91CD3F27CFB3638948BDAD62AE5536523696421A", + ["SftpFileSystem.dll"] = "6A3CB9D38956D096FC5FEA5BEA4B6D7D6C1A8BD5A910BA6DB3AF7F341B788352", + ["SftpFileSystem.dll (x86)"] = "75E759220BB784944BF4BE3086FF76CEFBA44FE015B08FEBD4F055649F0E1CF1", + ["SftpFileSystem.Resources.dll"] = "B3CF8FDE5F8BB70A2F6C4699A8A41FC885C63A63D3CCC7DD029B4B393494E56D", + ["SftpFileSystem.Resources.dll (x86)"] = "B3CF8FDE5F8BB70A2F6C4699A8A41FC885C63A63D3CCC7DD029B4B393494E56D", }; }