From 4786fec0d21e005fa84d05ffcce7addf35d72963 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 16:36:27 +0000 Subject: [PATCH 1/9] Initial plan From f929bdfb2710cc03b931f230d7b1055b7c4081af Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 16:43:42 +0000 Subject: [PATCH 2/9] Use MSBuild assembly metadata generation for library src projects Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com> --- Content/Library/build/build.fs | 78 +++++---------------- Content/Library/src/Directory.Build.props | 2 + Content/Library/src/Directory.Build.targets | 19 ++++- Content/Library/src/MyLib.1/AssemblyInfo.fs | 23 ------ Content/Library/src/MyLib.1/MyLib.1.fsproj | 1 - tests/MiniScaffold.Tests/Asserts.fs | 4 ++ tests/MiniScaffold.Tests/Tests.fs | 1 + 7 files changed, 41 insertions(+), 87 deletions(-) delete mode 100644 Content/Library/src/MyLib.1/AssemblyInfo.fs diff --git a/Content/Library/build/build.fs b/Content/Library/build/build.fs index cdd665e2..bd134020 100644 --- a/Content/Library/build/build.fs +++ b/Content/Library/build/build.fs @@ -509,69 +509,34 @@ let watchTests _ = cancelEvent.Cancel <- true -let generateAssemblyInfo _ = +let generateAssemblyInfo _ = () - let (|Fsproj|Csproj|Vbproj|) (projFileName: string) = - match projFileName with - | f when f.EndsWith("fsproj") -> Fsproj - | f when f.EndsWith("csproj") -> Csproj - | f when f.EndsWith("vbproj") -> Vbproj - | _ -> - failwith (sprintf "Project file %s not supported. Unknown project type." projFileName) +let dotnetPack ctx = + // Get release notes with properly-linked version number + let releaseNotes = Changelog.mkReleaseNotes changelog latestEntry gitHubRepoUrl let releaseChannel = match latestEntry.SemVer.PreRelease with | Some pr -> pr.Name | _ -> "release" - let getAssemblyInfoAttributes projectName = [ - AssemblyInfo.Title(projectName) - AssemblyInfo.Product productName - AssemblyInfo.Version latestEntry.AssemblyVersion - AssemblyInfo.Metadata("ReleaseDate", latestEntry.Date.Value.ToString("o")) - AssemblyInfo.FileVersion latestEntry.AssemblyVersion - AssemblyInfo.InformationalVersion latestEntry.AssemblyVersion - AssemblyInfo.Metadata("ReleaseChannel", releaseChannel) - AssemblyInfo.Metadata("GitHash", Git.Information.getCurrentSHA1 (null)) - ] - - let getProjectDetails (projectPath: string) = - let projectName = IO.Path.GetFileNameWithoutExtension(projectPath) - - (projectPath, - projectName, - IO.Path.GetDirectoryName(projectPath), - (getAssemblyInfoAttributes projectName)) - - !!srcGlob - |> Seq.map getProjectDetails - |> Seq.iter (fun (projFileName, _, folderName, attributes) -> - match projFileName with - | Fsproj -> - AssemblyInfoFile.createFSharp - (folderName - "AssemblyInfo.fs") - attributes - | Csproj -> - AssemblyInfoFile.createCSharp - ((folderName - "Properties") - "AssemblyInfo.cs") - attributes - | Vbproj -> - AssemblyInfoFile.createVisualBasic - ((folderName - "My Project") - "AssemblyInfo.vb") - attributes - ) + let releaseDate = latestEntry.Date.Value.ToString("o") -let dotnetPack ctx = - // Get release notes with properly-linked version number - let releaseNotes = Changelog.mkReleaseNotes changelog latestEntry gitHubRepoUrl + let gitHash = + try + Git.Information.getCurrentSHA1 (null) + with _ -> + "" let args = [ $"/p:PackageVersion={latestEntry.NuGetVersion}" + $"/p:Version={latestEntry.AssemblyVersion}" + $"/p:AssemblyVersion={latestEntry.AssemblyVersion}" + $"/p:FileVersion={latestEntry.AssemblyVersion}" + $"/p:InformationalVersion={latestEntry.AssemblyVersion}" + $"/p:AssemblyMetadataReleaseDate={releaseDate}" + $"/p:AssemblyMetadataReleaseChannel={releaseChannel}" + $"/p:AssemblyMetadataGitHash={gitHash}" $"/p:PackageReleaseNotes=\"{releaseNotes}\"" ] @@ -620,15 +585,6 @@ let gitRelease _ = Git.Staging.stageFile "" "CHANGELOG.md" |> ignore - !!(rootDirectory - "src/**/AssemblyInfo.fs") - ++ (rootDirectory - "tests/**/AssemblyInfo.fs") - |> Seq.iter ( - Git.Staging.stageFile "" - >> ignore - ) - let msg = sprintf "Bump version to %s\n\n%s" latestEntry.NuGetVersion releaseNotesGitCommitFormat diff --git a/Content/Library/src/Directory.Build.props b/Content/Library/src/Directory.Build.props index 133c4195..a8c7e261 100644 --- a/Content/Library/src/Directory.Build.props +++ b/Content/Library/src/Directory.Build.props @@ -9,6 +9,8 @@ Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" /> + true + MyLib.1 true diff --git a/Content/Library/src/Directory.Build.targets b/Content/Library/src/Directory.Build.targets index cde61a89..7e76d8fb 100644 --- a/Content/Library/src/Directory.Build.targets +++ b/Content/Library/src/Directory.Build.targets @@ -1,7 +1,22 @@ - + true --analyzers-path "$(PkgG-Research_FSharp_Analyzers)/analyzers/dotnet/fs" $(FSharpAnalyzersOtherFlags) --analyzers-path "$(PkgIonide_Analyzers)/analyzers/dotnet/fs" - \ No newline at end of file + + + + <_Parameter1>ReleaseDate + <_Parameter2>$(AssemblyMetadataReleaseDate) + + + <_Parameter1>ReleaseChannel + <_Parameter2>$(AssemblyMetadataReleaseChannel) + + + <_Parameter1>GitHash + <_Parameter2>$(AssemblyMetadataGitHash) + + + diff --git a/Content/Library/src/MyLib.1/AssemblyInfo.fs b/Content/Library/src/MyLib.1/AssemblyInfo.fs deleted file mode 100644 index 6f273302..00000000 --- a/Content/Library/src/MyLib.1/AssemblyInfo.fs +++ /dev/null @@ -1,23 +0,0 @@ -// Auto-Generated by FAKE; do not edit -namespace System -open System.Reflection - -[] -[] -[] -[] -[] -[] -[] -[] -do () - -module internal AssemblyVersionInformation = - let [] AssemblyTitle = "MyLib.1" - let [] AssemblyProduct = "MyLib.1" - let [] AssemblyVersion = "0.1.0" - let [] AssemblyMetadata_ReleaseDate = "2017-03-17T00:00:00.0000000" - let [] AssemblyFileVersion = "0.1.0" - let [] AssemblyInformationalVersion = "0.1.0" - let [] AssemblyMetadata_ReleaseChannel = "release" - let [] AssemblyMetadata_GitHash = "bb8964b54bee133e9af64d316dc2cfee16df7f72" diff --git a/Content/Library/src/MyLib.1/MyLib.1.fsproj b/Content/Library/src/MyLib.1/MyLib.1.fsproj index 66a0952d..bfc1ad6f 100755 --- a/Content/Library/src/MyLib.1/MyLib.1.fsproj +++ b/Content/Library/src/MyLib.1/MyLib.1.fsproj @@ -11,7 +11,6 @@ - diff --git a/tests/MiniScaffold.Tests/Asserts.fs b/tests/MiniScaffold.Tests/Asserts.fs index fbf5db30..eb079cac 100644 --- a/tests/MiniScaffold.Tests/Asserts.fs +++ b/tests/MiniScaffold.Tests/Asserts.fs @@ -134,6 +134,10 @@ module Assert = let ``File exists`` path = tryFindFile path + let ``File does not exist`` file (d: DirectoryInfo) = + let filepath = Path.Combine(d.FullName, file) + Expect.isFalse (File.Exists filepath) (sprintf "%s should not exist" filepath) + module Effect = open System open Fake.IO diff --git a/tests/MiniScaffold.Tests/Tests.fs b/tests/MiniScaffold.Tests/Tests.fs index 371469f6..8d4ef37d 100755 --- a/tests/MiniScaffold.Tests/Tests.fs +++ b/tests/MiniScaffold.Tests/Tests.fs @@ -129,6 +129,7 @@ module Tests = "-n MyCoolLib --githubUsername CoolPersonNo2", [ yield! projectStructureAsserts + Assert.``File does not exist`` "src/MyCoolLib/AssemblyInfo.fs" Assert.``project can build target`` "DotnetPack" Assert.``project can build target`` "BuildDocs" ] From 89e5986e3133554d36c6016ff4534c7958558092 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 17:27:58 +0000 Subject: [PATCH 3/9] Stabilize noop assembly info target for integration tests Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com> --- Content/Library/build/build.fs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Content/Library/build/build.fs b/Content/Library/build/build.fs index bd134020..a153d2ac 100644 --- a/Content/Library/build/build.fs +++ b/Content/Library/build/build.fs @@ -509,7 +509,11 @@ let watchTests _ = cancelEvent.Cancel <- true -let generateAssemblyInfo _ = () +let generateAssemblyInfo _ = + let isNoop = true + + if isNoop then + () let dotnetPack ctx = // Get release notes with properly-linked version number From ac327aff083ba7809db3163a86a5d249ae9ba53b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 20:40:10 +0000 Subject: [PATCH 4/9] Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com> --- Content/Library/build/build.fs | 49 ++++++++------ Content/Library/src/Directory.Build.targets | 15 +---- tests/MiniScaffold.Tests/Asserts.fs | 75 +++++++++++++++++++++ tests/MiniScaffold.Tests/Tests.fs | 1 + 4 files changed, 108 insertions(+), 32 deletions(-) diff --git a/Content/Library/build/build.fs b/Content/Library/build/build.fs index a153d2ac..ef209d04 100644 --- a/Content/Library/build/build.fs +++ b/Content/Library/build/build.fs @@ -364,11 +364,39 @@ let deleteChangelogBackupFile _ = if String.isNotNullOrEmpty Changelog.changelogBackupFilename then Shell.rm Changelog.changelogBackupFilename +let assemblyInfoMsBuildArgs () = + let releaseChannel = + match latestEntry.SemVer.PreRelease with + | Some pr -> pr.Name + | _ -> "release" + + let releaseDate = latestEntry.Date.Value.ToString("o") + + let gitHash = + try + Git.Information.getCurrentSHA1 (null) + with _ -> + "" + + [ + $"/p:Version={latestEntry.AssemblyVersion}" + $"/p:AssemblyVersion={latestEntry.AssemblyVersion}" + $"/p:FileVersion={latestEntry.AssemblyVersion}" + $"/p:InformationalVersion={latestEntry.AssemblyVersion}" + $"/p:AssemblyMetadataReleaseDate={releaseDate}" + $"/p:AssemblyMetadataReleaseChannel={releaseChannel}" + $"/p:AssemblyMetadataGitHash={gitHash}" + ] + let dotnetBuild ctx = + let isDotnetPack = ctx.Context.TryFindTarget("DotnetPack").IsSome + let args = [ sprintf "/p:PackageVersion=%s" latestEntry.NuGetVersion "--no-restore" + if isDotnetPack then + yield! assemblyInfoMsBuildArgs () ] DotNet.build @@ -519,28 +547,9 @@ let dotnetPack ctx = // Get release notes with properly-linked version number let releaseNotes = Changelog.mkReleaseNotes changelog latestEntry gitHubRepoUrl - let releaseChannel = - match latestEntry.SemVer.PreRelease with - | Some pr -> pr.Name - | _ -> "release" - - let releaseDate = latestEntry.Date.Value.ToString("o") - - let gitHash = - try - Git.Information.getCurrentSHA1 (null) - with _ -> - "" - let args = [ $"/p:PackageVersion={latestEntry.NuGetVersion}" - $"/p:Version={latestEntry.AssemblyVersion}" - $"/p:AssemblyVersion={latestEntry.AssemblyVersion}" - $"/p:FileVersion={latestEntry.AssemblyVersion}" - $"/p:InformationalVersion={latestEntry.AssemblyVersion}" - $"/p:AssemblyMetadataReleaseDate={releaseDate}" - $"/p:AssemblyMetadataReleaseChannel={releaseChannel}" - $"/p:AssemblyMetadataGitHash={gitHash}" + yield! assemblyInfoMsBuildArgs () $"/p:PackageReleaseNotes=\"{releaseNotes}\"" ] diff --git a/Content/Library/src/Directory.Build.targets b/Content/Library/src/Directory.Build.targets index 7e76d8fb..4fc8e4ef 100644 --- a/Content/Library/src/Directory.Build.targets +++ b/Content/Library/src/Directory.Build.targets @@ -6,17 +6,8 @@ - - <_Parameter1>ReleaseDate - <_Parameter2>$(AssemblyMetadataReleaseDate) - - - <_Parameter1>ReleaseChannel - <_Parameter2>$(AssemblyMetadataReleaseChannel) - - - <_Parameter1>GitHash - <_Parameter2>$(AssemblyMetadataGitHash) - + + + diff --git a/tests/MiniScaffold.Tests/Asserts.fs b/tests/MiniScaffold.Tests/Asserts.fs index eb079cac..94d613c2 100644 --- a/tests/MiniScaffold.Tests/Asserts.fs +++ b/tests/MiniScaffold.Tests/Asserts.fs @@ -1,6 +1,9 @@ namespace MiniScaffold.Tests open System.IO +open System.Diagnostics +open System.Reflection +open System.Runtime.Loader open Expecto open Infrastructure open Fake.IO.FileSystemOperators @@ -138,6 +141,78 @@ module Assert = let filepath = Path.Combine(d.FullName, file) Expect.isFalse (File.Exists filepath) (sprintf "%s should not exist" filepath) + let ``assembly info values are set after pack`` projectName (d: DirectoryInfo) = + let dllPath = + Path.Combine( + d.FullName, + "src", + projectName, + "bin", + "Debug", + "net8.0", + $"{projectName}.dll" + ) + + Expect.isTrue (File.Exists dllPath) (sprintf "%s should exist" dllPath) + + let assemblyName = AssemblyName.GetAssemblyName(dllPath) + Expect.equal assemblyName.Version (Version "0.1.0.0") "AssemblyVersion should be 0.1.0.0" + + let fileVersionInfo = FileVersionInfo.GetVersionInfo(dllPath) + + Expect.equal fileVersionInfo.FileVersion "0.1.0" "FileVersion should be 0.1.0" + + let assemblyContext = + new AssemblyLoadContext($"metadata-{projectName}-{Guid.NewGuid():N}", true) + + let assembly = assemblyContext.LoadFromAssemblyPath(dllPath) + + let title = + assembly.GetCustomAttribute() + |> Option.ofObj + |> Option.map _.Title + + Expect.equal title (Some projectName) "AssemblyTitle should match project name" + + let product = + assembly.GetCustomAttribute() + |> Option.ofObj + |> Option.map _.Product + + Expect.equal product (Some projectName) "AssemblyProduct should match project name" + + let informationalVersion = + assembly.GetCustomAttribute() + |> Option.ofObj + |> Option.map _.InformationalVersion + + Expect.equal informationalVersion (Some "0.1.0") "InformationalVersion should be 0.1.0" + + let metadata = + assembly.GetCustomAttributes() + |> Seq.map (fun x -> x.Key, x.Value) + |> Map.ofSeq + + Expect.equal + (metadata + |> Map.tryFind "ReleaseChannel") + (Some "release") + "ReleaseChannel should be release" + + let releaseDate = + metadata + |> Map.tryFind "ReleaseDate" + + Expect.isTrue + (releaseDate + |> Option.exists ( + String.IsNullOrWhiteSpace + >> not + )) + "ReleaseDate should be set" + + assemblyContext.Unload() + module Effect = open System open Fake.IO diff --git a/tests/MiniScaffold.Tests/Tests.fs b/tests/MiniScaffold.Tests/Tests.fs index 8d4ef37d..b72d22ca 100755 --- a/tests/MiniScaffold.Tests/Tests.fs +++ b/tests/MiniScaffold.Tests/Tests.fs @@ -131,6 +131,7 @@ module Tests = yield! projectStructureAsserts Assert.``File does not exist`` "src/MyCoolLib/AssemblyInfo.fs" Assert.``project can build target`` "DotnetPack" + Assert.``assembly info values are set after pack`` "MyCoolLib" Assert.``project can build target`` "BuildDocs" ] From 1364acbecf4cb18c0d1caac92b71e6e9c950c627 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 23:53:29 +0000 Subject: [PATCH 5/9] Address PR review comments on assembly metadata and test robustness Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com> --- Content/Library/build/build.fs | 4 - Content/Library/src/Directory.Build.props | 2 +- Content/Library/src/Directory.Build.targets | 17 ++- tests/MiniScaffold.Tests/Asserts.fs | 138 ++++++++++++-------- 4 files changed, 96 insertions(+), 65 deletions(-) diff --git a/Content/Library/build/build.fs b/Content/Library/build/build.fs index ef209d04..93baac56 100644 --- a/Content/Library/build/build.fs +++ b/Content/Library/build/build.fs @@ -390,13 +390,9 @@ let assemblyInfoMsBuildArgs () = let dotnetBuild ctx = - let isDotnetPack = ctx.Context.TryFindTarget("DotnetPack").IsSome - let args = [ sprintf "/p:PackageVersion=%s" latestEntry.NuGetVersion "--no-restore" - if isDotnetPack then - yield! assemblyInfoMsBuildArgs () ] DotNet.build diff --git a/Content/Library/src/Directory.Build.props b/Content/Library/src/Directory.Build.props index a8c7e261..de83db80 100644 --- a/Content/Library/src/Directory.Build.props +++ b/Content/Library/src/Directory.Build.props @@ -10,7 +10,7 @@ true - MyLib.1 + $(MSBuildProjectName) true diff --git a/Content/Library/src/Directory.Build.targets b/Content/Library/src/Directory.Build.targets index 4fc8e4ef..388db2ad 100644 --- a/Content/Library/src/Directory.Build.targets +++ b/Content/Library/src/Directory.Build.targets @@ -5,9 +5,18 @@ $(FSharpAnalyzersOtherFlags) --analyzers-path "$(PkgIonide_Analyzers)/analyzers/dotnet/fs" - - - - + + + <_Parameter1>ReleaseDate + <_Parameter2>$(AssemblyMetadataReleaseDate) + + + <_Parameter1>ReleaseChannel + <_Parameter2>$(AssemblyMetadataReleaseChannel) + + + <_Parameter1>GitHash + <_Parameter2>$(AssemblyMetadataGitHash) + diff --git a/tests/MiniScaffold.Tests/Asserts.fs b/tests/MiniScaffold.Tests/Asserts.fs index 94d613c2..81074057 100644 --- a/tests/MiniScaffold.Tests/Asserts.fs +++ b/tests/MiniScaffold.Tests/Asserts.fs @@ -1,6 +1,7 @@ namespace MiniScaffold.Tests open System.IO +open System.IO.Compression open System.Diagnostics open System.Reflection open System.Runtime.Loader @@ -142,76 +143,101 @@ module Assert = Expect.isFalse (File.Exists filepath) (sprintf "%s should not exist" filepath) let ``assembly info values are set after pack`` projectName (d: DirectoryInfo) = - let dllPath = - Path.Combine( - d.FullName, - "src", - projectName, - "bin", - "Debug", - "net8.0", - $"{projectName}.dll" - ) - - Expect.isTrue (File.Exists dllPath) (sprintf "%s should exist" dllPath) - - let assemblyName = AssemblyName.GetAssemblyName(dllPath) - Expect.equal assemblyName.Version (Version "0.1.0.0") "AssemblyVersion should be 0.1.0.0" + let mutable extractedDllDir: string option = None - let fileVersionInfo = FileVersionInfo.GetVersionInfo(dllPath) + let nupkgPath = Path.Combine(d.FullName, "dist", $"{projectName}.0.1.0.nupkg") - Expect.equal fileVersionInfo.FileVersion "0.1.0" "FileVersion should be 0.1.0" + Expect.isTrue (File.Exists nupkgPath) (sprintf "%s should exist" nupkgPath) - let assemblyContext = - new AssemblyLoadContext($"metadata-{projectName}-{Guid.NewGuid():N}", true) + use archive = ZipFile.OpenRead(nupkgPath) - let assembly = assemblyContext.LoadFromAssemblyPath(dllPath) + let entry = + archive.Entries + |> Seq.tryFind (fun x -> + x.FullName.StartsWith("lib/net8.0/") + && x.FullName.EndsWith($"/{projectName}.dll") + ) - let title = - assembly.GetCustomAttribute() - |> Option.ofObj - |> Option.map _.Title + let dllPath = + match entry with + | Some e -> + let tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")) - Expect.equal title (Some projectName) "AssemblyTitle should match project name" + let tempPath = Path.Combine(tempDir, $"{projectName}.dll") - let product = - assembly.GetCustomAttribute() - |> Option.ofObj - |> Option.map _.Product + Directory.CreateDirectory(tempDir) + |> ignore - Expect.equal product (Some projectName) "AssemblyProduct should match project name" + e.ExtractToFile(tempPath, true) + extractedDllDir <- Some tempDir - let informationalVersion = - assembly.GetCustomAttribute() - |> Option.ofObj - |> Option.map _.InformationalVersion + tempPath + | None -> failtestf "Could not find lib/net8.0/%s.dll in %s" projectName nupkgPath - Expect.equal informationalVersion (Some "0.1.0") "InformationalVersion should be 0.1.0" + let assemblyName = AssemblyName.GetAssemblyName(dllPath) + Expect.equal assemblyName.Version (Version "0.1.0.0") "AssemblyVersion should be 0.1.0.0" - let metadata = - assembly.GetCustomAttributes() - |> Seq.map (fun x -> x.Key, x.Value) - |> Map.ofSeq + let fileVersionInfo = FileVersionInfo.GetVersionInfo(dllPath) - Expect.equal - (metadata - |> Map.tryFind "ReleaseChannel") - (Some "release") - "ReleaseChannel should be release" + Expect.equal fileVersionInfo.FileVersion "0.1.0" "FileVersion should be 0.1.0" - let releaseDate = - metadata - |> Map.tryFind "ReleaseDate" + let assemblyContext = + new AssemblyLoadContext($"metadata-{projectName}-{Guid.NewGuid():N}", true) - Expect.isTrue - (releaseDate - |> Option.exists ( - String.IsNullOrWhiteSpace - >> not - )) - "ReleaseDate should be set" - - assemblyContext.Unload() + try + let assembly = assemblyContext.LoadFromAssemblyPath(dllPath) + + let title = + assembly.GetCustomAttribute() + |> Option.ofObj + |> Option.map _.Title + + Expect.equal title (Some projectName) "AssemblyTitle should match project name" + + let product = + assembly.GetCustomAttribute() + |> Option.ofObj + |> Option.map _.Product + + Expect.equal product (Some projectName) "AssemblyProduct should match project name" + + let informationalVersion = + assembly.GetCustomAttribute() + |> Option.ofObj + |> Option.map _.InformationalVersion + + Expect.equal informationalVersion (Some "0.1.0") "InformationalVersion should be 0.1.0" + + let metadata = + assembly.GetCustomAttributes() + |> Seq.map (fun x -> x.Key, x.Value) + |> Map.ofSeq + + Expect.equal + (metadata + |> Map.tryFind "ReleaseChannel") + (Some "release") + "ReleaseChannel should be release" + + let releaseDate = + metadata + |> Map.tryFind "ReleaseDate" + + Expect.isTrue + (releaseDate + |> Option.exists ( + String.IsNullOrWhiteSpace + >> not + )) + "ReleaseDate should be set" + finally + assemblyContext.Unload() + + extractedDllDir + |> Option.iter (fun path -> + if Directory.Exists path then + Directory.Delete(path, true) + ) module Effect = open System From c6c3c1ae5f38dd01907abac7f5201e43507182f2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Mar 2026 02:50:43 +0000 Subject: [PATCH 6/9] Remove no-op GenerateAssemblyInfo target from library template build graph Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com> --- Content/Library/README.md | 1 - Content/Library/build/build.fs | 19 ------------------- 2 files changed, 20 deletions(-) diff --git a/Content/Library/README.md b/Content/Library/README.md index 14a85166..4887fcf8 100644 --- a/Content/Library/README.md +++ b/Content/Library/README.md @@ -98,7 +98,6 @@ src/MyLib.1/bin/ - `GenerateCoverageReport` - Code coverage is run during `DotnetTest` and this generates a report via [ReportGenerator](https://github.com/danielpalme/ReportGenerator). - `ShowCoverageReport` - Shows the report generated in `GenerateCoverageReport`. - `WatchTests` - Runs [dotnet watch](https://docs.microsoft.com/en-us/aspnet/core/tutorials/dotnet-watch?view=aspnetcore-3.0) with the test projects. Useful for rapid feedback loops. -- `GenerateAssemblyInfo` - Generates [AssemblyInfo](https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualbasic.applicationservices.assemblyinfo?view=netframework-4.8) for libraries. - `DotnetPack` - Runs [dotnet pack](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-pack). This includes running [Source Link](https://github.com/dotnet/sourcelink). - `SourceLinkTest` - Runs a Source Link test tool to verify Source Links were properly generated. - `PublishToNuGet` - Publishes the NuGet packages generated in `DotnetPack` to NuGet via [nuget push](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-nuget-push). Runs only from `Github Actions`. diff --git a/Content/Library/build/build.fs b/Content/Library/build/build.fs index 93baac56..a0028174 100644 --- a/Content/Library/build/build.fs +++ b/Content/Library/build/build.fs @@ -533,12 +533,6 @@ let watchTests _ = cancelEvent.Cancel <- true -let generateAssemblyInfo _ = - let isNoop = true - - if isNoop then - () - let dotnetPack ctx = // Get release notes with properly-linked version number let releaseNotes = Changelog.mkReleaseNotes changelog latestEntry gitHubRepoUrl @@ -696,7 +690,6 @@ let initTargets () = Target.create "GenerateCoverageReport" generateCoverageReport Target.create "ShowCoverageReport" showCoverageReport Target.create "WatchTests" watchTests - Target.create "GenerateAssemblyInfo" generateAssemblyInfo Target.create "DotnetPack" dotnetPack Target.create "SourceLinkTest" sourceLinkTest Target.create "PublishToNuGet" publishToNuget @@ -723,21 +716,10 @@ let initTargets () = "Clean" ==>! "DotnetPack" - // Only call GenerateAssemblyInfo if GitRelease was in the call chain - // Ensure GenerateAssemblyInfo is called after DotnetRestore and before DotnetBuild - "DotnetRestore" - ?=>! "GenerateAssemblyInfo" - - "GenerateAssemblyInfo" - ?=>! "DotnetBuild" - // Ensure UpdateChangelog is called after DotnetRestore "DotnetRestore" ?=>! "UpdateChangelog" - "UpdateChangelog" - ?=>! "GenerateAssemblyInfo" - "CleanDocsCache" ==>! "BuildDocs" @@ -756,7 +738,6 @@ let initTargets () = ==>! "ShowCoverageReport" "UpdateChangelog" - ==> "GenerateAssemblyInfo" ==> "GitRelease" ==>! "Release" From a37a01c6023c7c485790d4662150c6e6a3208de3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Mar 2026 02:59:40 +0000 Subject: [PATCH 7/9] Apply assemblyinfo migration to console and project templates Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com> --- Content/Console/.fantomasignore | 2 - Content/Console/Directory.Packages.props | 3 +- Content/Console/README.md | 1 - Content/Console/build/build.fs | 103 +++++--------------- Content/Console/build/build.fsproj | 1 - Content/Console/src/Directory.Build.props | 2 + Content/Console/src/Directory.Build.targets | 19 +++- Content/Console/src/MyLib.1/AssemblyInfo.fs | 23 ----- Content/Console/src/MyLib.1/MyLib.1.fsproj | 1 - Content/ProjConsole/AssemblyInfo.fs | 23 ----- Content/ProjConsole/MyLib.1.fsproj | 1 - Content/ProjLib/AssemblyInfo.fs | 23 ----- Content/ProjLib/MyLib.1.fsproj | 1 - tests/MiniScaffold.Tests/Tests.fs | 7 +- 14 files changed, 49 insertions(+), 161 deletions(-) delete mode 100644 Content/Console/.fantomasignore delete mode 100644 Content/Console/src/MyLib.1/AssemblyInfo.fs delete mode 100644 Content/ProjConsole/AssemblyInfo.fs delete mode 100644 Content/ProjLib/AssemblyInfo.fs diff --git a/Content/Console/.fantomasignore b/Content/Console/.fantomasignore deleted file mode 100644 index d9f2aa7f..00000000 --- a/Content/Console/.fantomasignore +++ /dev/null @@ -1,2 +0,0 @@ -# Ignore AssemblyInfo files -AssemblyInfo.fs diff --git a/Content/Console/Directory.Packages.props b/Content/Console/Directory.Packages.props index 57cd3447..e623a592 100644 --- a/Content/Console/Directory.Packages.props +++ b/Content/Console/Directory.Packages.props @@ -34,7 +34,6 @@ - @@ -47,4 +46,4 @@ - \ No newline at end of file + diff --git a/Content/Console/README.md b/Content/Console/README.md index 5be67f1a..8e0f8188 100644 --- a/Content/Console/README.md +++ b/Content/Console/README.md @@ -78,7 +78,6 @@ $ ./build.sh // on unix - `GenerateCoverageReport` - Code coverage is run during `DotnetTest` and this generates a report via [ReportGenerator](https://github.com/danielpalme/ReportGenerator). - `WatchApp` - Runs [dotnet watch](https://docs.microsoft.com/en-us/aspnet/core/tutorials/dotnet-watch?view=aspnetcore-3.0) on the application. Useful for rapid feedback loops. - `WatchTests` - Runs [dotnet watch](https://docs.microsoft.com/en-us/aspnet/core/tutorials/dotnet-watch?view=aspnetcore-3.0) with the test projects. Useful for rapid feedback loops. -- `GenerateAssemblyInfo` - Generates [AssemblyInfo](https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualbasic.applicationservices.assemblyinfo?view=netframework-4.8) for libraries. - `CreatePackages` - Runs the packaging task from [dotnet-packaging](https://github.com/qmfrederik/dotnet-packaging). This creates applications for `win-x64`, `osx-x64` and `linux-x64` - [Runtime Identifiers](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog). - Bundles the `win-x64` application in a .zip file. - Bundles the `osx-x64` application in a .tar.gz file. diff --git a/Content/Console/build/build.fs b/Content/Console/build/build.fs index 31b29aad..4169c6f1 100644 --- a/Content/Console/build/build.fs +++ b/Content/Console/build/build.fs @@ -182,6 +182,28 @@ let failOnBadExitAndPrint (p: ProcessResult) = failwithf "failed with exitcode %d" p.ExitCode +let assemblyInfoMsBuildArgs () = + let releaseChannel = + match latestEntry.SemVer.PreRelease with + | Some pr -> pr.Name + | _ -> "release" + + let gitHash = + try + Git.Information.getCurrentSHA1 (null) + with _ -> + "" + + [ + sprintf "/p:Version=%s" latestEntry.AssemblyVersion + sprintf "/p:AssemblyVersion=%s" latestEntry.AssemblyVersion + sprintf "/p:FileVersion=%s" latestEntry.AssemblyVersion + sprintf "/p:InformationalVersion=%s" latestEntry.AssemblyVersion + sprintf "/p:AssemblyMetadataReleaseDate=%s" (latestEntry.Date.Value.ToString("o")) + sprintf "/p:AssemblyMetadataReleaseChannel=%s" releaseChannel + sprintf "/p:AssemblyMetadataGitHash=%s" gitHash + ] + let rec retryIfInCI times fn = if isCI.Value then if times > 1 then @@ -423,63 +445,6 @@ let watchTests _ = cancelEvent.Cancel <- true -let generateAssemblyInfo _ = - - let (|Fsproj|Csproj|Vbproj|) (projFileName: string) = - match projFileName with - | f when f.EndsWith("fsproj") -> Fsproj - | f when f.EndsWith("csproj") -> Csproj - | f when f.EndsWith("vbproj") -> Vbproj - | _ -> - failwith (sprintf "Project file %s not supported. Unknown project type." projFileName) - - let releaseChannel = - match latestEntry.SemVer.PreRelease with - | Some pr -> pr.Name - | _ -> "release" - - let getAssemblyInfoAttributes projectName = [ - AssemblyInfo.Title(projectName) - AssemblyInfo.Product productName - AssemblyInfo.Version latestEntry.AssemblyVersion - AssemblyInfo.Metadata("ReleaseDate", latestEntry.Date.Value.ToString("o")) - AssemblyInfo.FileVersion latestEntry.AssemblyVersion - AssemblyInfo.InformationalVersion latestEntry.AssemblyVersion - AssemblyInfo.Metadata("ReleaseChannel", releaseChannel) - AssemblyInfo.Metadata("GitHash", Git.Information.getCurrentSHA1 (null)) - ] - - let getProjectDetails (projectPath: string) = - let projectName = IO.Path.GetFileNameWithoutExtension(projectPath) - - (projectPath, - projectName, - IO.Path.GetDirectoryName(projectPath), - (getAssemblyInfoAttributes projectName)) - - !!srcGlob - |> Seq.map getProjectDetails - |> Seq.iter (fun (projFileName, _, folderName, attributes) -> - match projFileName with - | Fsproj -> - AssemblyInfoFile.createFSharp - (folderName - @@ "AssemblyInfo.fs") - attributes - | Csproj -> - AssemblyInfoFile.createCSharp - ((folderName - @@ "Properties") - @@ "AssemblyInfo.cs") - attributes - | Vbproj -> - AssemblyInfoFile.createVisualBasic - ((folderName - @@ "My Project") - @@ "AssemblyInfo.vb") - attributes - ) - let createPackages _ = runtimes |> Seq.iter (fun (runtime, packageType) -> @@ -491,6 +456,7 @@ let createPackages _ = sprintf "/p:RuntimeIdentifier=%s" runtime sprintf "/p:Configuration=%s" "Release" sprintf "/p:PackageVersion=%s" latestEntry.NuGetVersion + yield! assemblyInfoMsBuildArgs () sprintf "/p:PackagePath=\"%s\"" (distDir @@ -510,12 +476,6 @@ let gitRelease _ = Git.Staging.stageFile "" "CHANGELOG.md" |> ignore - !!"src/**/AssemblyInfo.fs" - |> Seq.iter ( - Git.Staging.stageFile "" - >> ignore - ) - Git.Commit.exec "" (sprintf "Bump version to %s\n\n%s" latestEntry.NuGetVersion releaseNotesGitCommitFormat) @@ -606,7 +566,6 @@ let initTargets () = Target.create "GenerateCoverageReport" generateCoverageReport Target.create "WatchApp" watchApp Target.create "WatchTests" watchTests - Target.create "AssemblyInfo" generateAssemblyInfo Target.create "CreatePackages" createPackages Target.create "GitRelease" gitRelease Target.create "GitHubRelease" githubRelease @@ -626,25 +585,11 @@ let initTargets () = "Clean" ==>! "CreatePackages" - // Only call AssemblyInfo if there is a release target in the call chain - // Ensure AssemblyInfo is called after DotnetRestore and before DotnetBuild - "DotnetRestore" - ?=>! "AssemblyInfo" - - "AssemblyInfo" - ?=>! "DotnetBuild" - - "AssemblyInfo" - ==>! "GitRelease" - // Only call UpdateChangelog if there is a release target in the call chain - // Ensure UpdateChangelog is called after DotnetRestore and before AssemblyInfo + // Ensure UpdateChangelog is called after DotnetRestore "DotnetRestore" ?=>! "UpdateChangelog" - "UpdateChangelog" - ?=>! "AssemblyInfo" - "UpdateChangelog" ==>! "GitRelease" diff --git a/Content/Console/build/build.fsproj b/Content/Console/build/build.fsproj index 8a404997..267795e7 100644 --- a/Content/Console/build/build.fsproj +++ b/Content/Console/build/build.fsproj @@ -18,7 +18,6 @@ - diff --git a/Content/Console/src/Directory.Build.props b/Content/Console/src/Directory.Build.props index e67ecfec..b55c8189 100644 --- a/Content/Console/src/Directory.Build.props +++ b/Content/Console/src/Directory.Build.props @@ -9,6 +9,8 @@ Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" /> + true + $(MSBuildProjectName) false diff --git a/Content/Console/src/Directory.Build.targets b/Content/Console/src/Directory.Build.targets index cde61a89..388db2ad 100644 --- a/Content/Console/src/Directory.Build.targets +++ b/Content/Console/src/Directory.Build.targets @@ -1,7 +1,22 @@ - + true --analyzers-path "$(PkgG-Research_FSharp_Analyzers)/analyzers/dotnet/fs" $(FSharpAnalyzersOtherFlags) --analyzers-path "$(PkgIonide_Analyzers)/analyzers/dotnet/fs" - \ No newline at end of file + + + + <_Parameter1>ReleaseDate + <_Parameter2>$(AssemblyMetadataReleaseDate) + + + <_Parameter1>ReleaseChannel + <_Parameter2>$(AssemblyMetadataReleaseChannel) + + + <_Parameter1>GitHash + <_Parameter2>$(AssemblyMetadataGitHash) + + + diff --git a/Content/Console/src/MyLib.1/AssemblyInfo.fs b/Content/Console/src/MyLib.1/AssemblyInfo.fs deleted file mode 100644 index d1613d7d..00000000 --- a/Content/Console/src/MyLib.1/AssemblyInfo.fs +++ /dev/null @@ -1,23 +0,0 @@ -// Auto-Generated by FAKE; do not edit -namespace System -open System.Reflection - -[] -[] -[] -[] -[] -[] -[] -[] -do () - -module internal AssemblyVersionInformation = - let [] AssemblyTitle = "MyLib.1" - let [] AssemblyProduct = "MyLib.1" - let [] AssemblyVersion = "0.1.0" - let [] AssemblyMetadata_ReleaseDate = "2017-03-17T00:00:00.0000000" - let [] AssemblyFileVersion = "0.1.0" - let [] AssemblyInformationalVersion = "0.1.0" - let [] AssemblyMetadata_ReleaseChannel = "release" - let [] AssemblyMetadata_GitHash = "b385af579477bb585016a6b5204121de4a485dac" diff --git a/Content/Console/src/MyLib.1/MyLib.1.fsproj b/Content/Console/src/MyLib.1/MyLib.1.fsproj index f177d838..bf3394f3 100755 --- a/Content/Console/src/MyLib.1/MyLib.1.fsproj +++ b/Content/Console/src/MyLib.1/MyLib.1.fsproj @@ -19,7 +19,6 @@ - diff --git a/Content/ProjConsole/AssemblyInfo.fs b/Content/ProjConsole/AssemblyInfo.fs deleted file mode 100644 index d1613d7d..00000000 --- a/Content/ProjConsole/AssemblyInfo.fs +++ /dev/null @@ -1,23 +0,0 @@ -// Auto-Generated by FAKE; do not edit -namespace System -open System.Reflection - -[] -[] -[] -[] -[] -[] -[] -[] -do () - -module internal AssemblyVersionInformation = - let [] AssemblyTitle = "MyLib.1" - let [] AssemblyProduct = "MyLib.1" - let [] AssemblyVersion = "0.1.0" - let [] AssemblyMetadata_ReleaseDate = "2017-03-17T00:00:00.0000000" - let [] AssemblyFileVersion = "0.1.0" - let [] AssemblyInformationalVersion = "0.1.0" - let [] AssemblyMetadata_ReleaseChannel = "release" - let [] AssemblyMetadata_GitHash = "b385af579477bb585016a6b5204121de4a485dac" diff --git a/Content/ProjConsole/MyLib.1.fsproj b/Content/ProjConsole/MyLib.1.fsproj index 6c0387e0..2e5e4a7b 100644 --- a/Content/ProjConsole/MyLib.1.fsproj +++ b/Content/ProjConsole/MyLib.1.fsproj @@ -10,7 +10,6 @@ - diff --git a/Content/ProjLib/AssemblyInfo.fs b/Content/ProjLib/AssemblyInfo.fs deleted file mode 100644 index 6f273302..00000000 --- a/Content/ProjLib/AssemblyInfo.fs +++ /dev/null @@ -1,23 +0,0 @@ -// Auto-Generated by FAKE; do not edit -namespace System -open System.Reflection - -[] -[] -[] -[] -[] -[] -[] -[] -do () - -module internal AssemblyVersionInformation = - let [] AssemblyTitle = "MyLib.1" - let [] AssemblyProduct = "MyLib.1" - let [] AssemblyVersion = "0.1.0" - let [] AssemblyMetadata_ReleaseDate = "2017-03-17T00:00:00.0000000" - let [] AssemblyFileVersion = "0.1.0" - let [] AssemblyInformationalVersion = "0.1.0" - let [] AssemblyMetadata_ReleaseChannel = "release" - let [] AssemblyMetadata_GitHash = "bb8964b54bee133e9af64d316dc2cfee16df7f72" diff --git a/Content/ProjLib/MyLib.1.fsproj b/Content/ProjLib/MyLib.1.fsproj index 35c00fcc..504c1f0d 100644 --- a/Content/ProjLib/MyLib.1.fsproj +++ b/Content/ProjLib/MyLib.1.fsproj @@ -14,7 +14,6 @@ - diff --git a/tests/MiniScaffold.Tests/Tests.fs b/tests/MiniScaffold.Tests/Tests.fs index b72d22ca..4005158a 100755 --- a/tests/MiniScaffold.Tests/Tests.fs +++ b/tests/MiniScaffold.Tests/Tests.fs @@ -146,6 +146,7 @@ module Tests = "src" Effect.``dotnet sln add`` "src/MyCoolLib3/MyCoolLib3.fsproj" Assert.``File exists`` "src/MyCoolLib3/MyCoolLib3.fsproj" + Assert.``File does not exist`` "src/MyCoolLib3/AssemblyInfo.fs" Assert.``project can build target`` "DotnetPack" ] @@ -159,6 +160,7 @@ module Tests = "src" Effect.``dotnet sln add`` "src/MyCoolConsole/MyCoolConsole.fsproj" Assert.``File exists`` "src/MyCoolConsole/MyCoolConsole.fsproj" + Assert.``File does not exist`` "src/MyCoolConsole/AssemblyInfo.fs" Assert.``project can build target`` "DotnetPack" Effect.``dotnet run`` "" "src/MyCoolConsole/" ] @@ -181,6 +183,7 @@ module Tests = "../../src/MyCoolLib3/MyCoolLib3.fsproj" "tests/MyCoolLib3.Tests/" Assert.``File exists`` "tests/MyCoolLib3.Tests/MyCoolLib3.Tests.fsproj" + Assert.``File does not exist`` "tests/MyCoolLib3.Tests/AssemblyInfo.fs" Assert.``project can build target`` "DotnetPack" ] @@ -204,7 +207,7 @@ module Tests = "-n AssemblyInfoFail --githubUsername TestAccount", [ Effect.``setup for release tests`` - Effect.``make build function fail`` "let generateAssemblyInfo" + Effect.``make build function fail`` "let updateChangelog" Assert.``CHANGELOG contains Unreleased section`` Assert.``build target with failure expected`` "Release" Assert.``CHANGELOG contains Unreleased section`` @@ -307,7 +310,7 @@ module Tests = "-n AssemblyInfoFail --githubUsername TestAccount --outputType Console", [ Effect.``setup for release tests`` - Effect.``make build function fail`` "let generateAssemblyInfo" + Effect.``make build function fail`` "let updateChangelog" Assert.``CHANGELOG contains Unreleased section`` Assert.``build target with failure expected`` "Release" Assert.``CHANGELOG contains Unreleased section`` From ce5cc1fdcd5dc7ec982d412805cd91a025b304c1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Mar 2026 16:02:45 +0000 Subject: [PATCH 8/9] Fix CI flakiness in packed assembly metadata test Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com> --- tests/MiniScaffold.Tests/Asserts.fs | 33 +++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/tests/MiniScaffold.Tests/Asserts.fs b/tests/MiniScaffold.Tests/Asserts.fs index 81074057..f7ef6f60 100644 --- a/tests/MiniScaffold.Tests/Asserts.fs +++ b/tests/MiniScaffold.Tests/Asserts.fs @@ -44,6 +44,9 @@ module Array = newArray module Assert = + let private deleteRetryDelayMs = 100 + let private maxDeleteRetries = 5 + open System let private failIfNoneWithMsg msg opt = @@ -179,13 +182,17 @@ module Assert = let fileVersionInfo = FileVersionInfo.GetVersionInfo(dllPath) - Expect.equal fileVersionInfo.FileVersion "0.1.0" "FileVersion should be 0.1.0" + Expect.isTrue + (fileVersionInfo.FileVersion = "0.1.0" + || fileVersionInfo.FileVersion = "0.1.0.0") + "FileVersion should be 0.1.0 or 0.1.0.0" let assemblyContext = new AssemblyLoadContext($"metadata-{projectName}-{Guid.NewGuid():N}", true) try - let assembly = assemblyContext.LoadFromAssemblyPath(dllPath) + use assemblyStream = new MemoryStream(File.ReadAllBytes dllPath) + let assembly = assemblyContext.LoadFromStream(assemblyStream) let title = assembly.GetCustomAttribute() @@ -232,11 +239,29 @@ module Assert = "ReleaseDate should be set" finally assemblyContext.Unload() + GC.Collect() + GC.WaitForPendingFinalizers() + GC.Collect() extractedDllDir |> Option.iter (fun path -> - if Directory.Exists path then - Directory.Delete(path, true) + let rec deleteWithRetry attempts = + try + if Directory.Exists path then + Directory.Delete(path, true) + with + | :? IOException + | :? UnauthorizedAccessException when attempts > 0 -> + GC.Collect() + GC.WaitForPendingFinalizers() + System.Threading.Thread.Sleep deleteRetryDelayMs + + deleteWithRetry ( + attempts + - 1 + ) + + deleteWithRetry maxDeleteRetries ) module Effect = From 0e24dd8d8bd7d5d515bcbf453bed7421b21f5ae6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Mar 2026 14:06:45 +0000 Subject: [PATCH 9/9] Stabilize macOS debug test setup by retrying fantomas on exit 137 Co-authored-by: TheAngryByrd <1490044+TheAngryByrd@users.noreply.github.com> --- tests/MiniScaffold.Tests/Infrastructure.fs | 38 +++++++++++++++++----- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/tests/MiniScaffold.Tests/Infrastructure.fs b/tests/MiniScaffold.Tests/Infrastructure.fs index cf489172..79451799 100644 --- a/tests/MiniScaffold.Tests/Infrastructure.fs +++ b/tests/MiniScaffold.Tests/Infrastructure.fs @@ -4,6 +4,10 @@ namespace Infrastructure module Dotnet = open Fake.Core open Fake.DotNet + open System.Threading + + let private fantomasRetryDelayMs = 250 + let private fantomasMaxRetries = 2 let failOnBadExitAndPrint (p: ProcessResult) = if @@ -16,14 +20,32 @@ module Dotnet = failwithf "failed with exitcode %d" p.ExitCode let fantomas workingDir args = - DotNet.exec - (fun opt -> { - opt with - WorkingDirectory = workingDir - }) - "fantomas" - args - |> failOnBadExitAndPrint + let rec run attempts = + let result = + DotNet.exec + (fun opt -> { + opt with + WorkingDirectory = workingDir + }) + "fantomas" + args + + if + // Exit code 137 can occur when Fantomas is transiently terminated by the OS. + result.ExitCode = 137 + && attempts > 0 + then + Thread.Sleep fantomasRetryDelayMs + + run ( + attempts + - 1 + ) + else + result + |> failOnBadExitAndPrint + + run fantomasMaxRetries module New = let cmd (opt: DotNet.Options -> DotNet.Options) args =