From 5540716d3f1757700a23b089ed901dec9102955c Mon Sep 17 00:00:00 2001 From: Tuomas Hietanen Date: Tue, 6 Aug 2024 13:15:01 +0100 Subject: [PATCH 1/4] SdkAssemblyResolver: Try-find was taking the first version, but we want to collect all versions and evaluate the selection later. --- .github/workflows/build_and_test.yml | 2 +- src/app/Fake.Runtime/SdkAssemblyResolver.fs | 78 ++++++++++++------- .../Fake.DotNet.Cli.IntegrationTests/Main.fs | 2 +- 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 18ecc251444..c30a4d5b13f 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -25,7 +25,7 @@ jobs: - name: add fake runner as a tool run: dotnet tool install fake-cli --add-source "./src/app/fake-cli/bin/Debug" --version 1.0.0-1 - name: Build - run: dotnet fake build --parallel 3 + run: dotnet fake -v build --parallel 3 -e FAKE_DETAILED_ERRORS=true - name: publish build artifacts uses: actions/upload-artifact@v4 with: diff --git a/src/app/Fake.Runtime/SdkAssemblyResolver.fs b/src/app/Fake.Runtime/SdkAssemblyResolver.fs index 575fc23cf78..43b7f4f0e71 100644 --- a/src/app/Fake.Runtime/SdkAssemblyResolver.fs +++ b/src/app/Fake.Runtime/SdkAssemblyResolver.fs @@ -149,14 +149,16 @@ type SdkAssemblyResolver(logLevel: Trace.VerboseLevel) = |> Async.AwaitTask |> Async.RunSynchronously |> List.ofSeq - |> List.find (fun product -> + |> List.filter (fun product -> this.SdkVersionRaws |> List.exists (fun raws -> product.ProductVersion.Equals raws)) - sdkVersionReleases.GetReleasesAsync() - |> Async.AwaitTask - |> Async.RunSynchronously - |> List.ofSeq + sdkVersionReleases + |> List.collect (fun rel -> + rel.GetReleasesAsync() + |> Async.AwaitTask + |> Async.RunSynchronously + |> List.ofSeq) |> Some with ex -> Trace.traceError $"Could not get SDK runtime version from network due to: {ex.Message}" @@ -179,7 +181,7 @@ type SdkAssemblyResolver(logLevel: Trace.VerboseLevel) = Trace.traceError $"Could not get SDK runtime version from cache due to: {ex.Message}" None - member this.GetProductReleaseForSdk(version: ReleaseVersion) = + member this.GetProductReleasesForSdk(version: ReleaseVersion) = let net60releases = if RuntimeResolverResolveMethod = "cache" then // for testing only! @@ -194,9 +196,14 @@ type SdkAssemblyResolver(logLevel: Trace.VerboseLevel) = |> List.ofSeq |> List.exists (fun sdk -> sdk.Version.Equals(version)) - net60releases |> Option.bind (List.tryFind sdkRelease) + match net60releases with + | None -> [] + | Some versions -> versions |> List.filter sdkRelease - member this.ResolveSdkRuntimeVersion() = + member this.GetProductReleaseForSdk(version: ReleaseVersion) = + this.GetProductReleasesForSdk version |> List.tryHead + + member this.ResolveSdkRuntimeVersions() = let versionOptions (options: DotNet.VersionOptions) = // If a custom CLI path is provided, configure the version command // to use that path. This really only accomodates a test scenarios @@ -208,43 +215,58 @@ type SdkAssemblyResolver(logLevel: Trace.VerboseLevel) = let sdkVersion = DotNet.getVersion versionOptions |> ReleaseVersion - match this.GetProductReleaseForSdk sdkVersion with - | Some release -> - let version = release.Runtime.Version.ToString() + match this.GetProductReleasesForSdk sdkVersion with + | [] -> + failwithf + $"Could not find a suitable .NET 6 runtime version matching SDK version: {sdkVersion.ToString()} (You can also try setting environment variable FAKE_SDK_RESOLVER_CUSTOM_DOTNET_VERSION to e.g. 8.0 )" + | releases -> + let versions = + releases |> List.map (fun release -> release.Runtime.Version.ToString()) if this.LogLevel.PrintVerbose then - Trace.trace $"Resolved runtime version: {version}" + versions + |> List.iter (fun version -> Trace.trace $"Resolved runtime version: {version}") - version + versions - | None -> - failwithf - $"Could not find a suitable .NET 6 runtime version matching SDK version: {sdkVersion.ToString()} (You can also try setting environment variable FAKE_SDK_RESOLVER_CUSTOM_DOTNET_VERSION to e.g. 8.0 )" + member this.ResolveSdkRuntimeVersion() = + this.ResolveSdkRuntimeVersions() |> Seq.head member this.SdkReferenceAssemblies() = + let runtimeVersions = this.ResolveSdkRuntimeVersions() + let referenceAssembliesPaths = - this.SdkVersionRaws - |> List.choose (fun rawVersion -> - this.ResolveDotNetRoot() - |> Option.map (fun dotnetRoot -> - dotnetRoot - "packs" - "Microsoft.NETCore.App.Ref" - this.ResolveSdkRuntimeVersion() - "ref" - "net" + rawVersion)) + runtimeVersions + |> List.map (fun runtimeVersion -> + this.SdkVersionRaws + |> List.choose (fun rawVersion -> + this.ResolveDotNetRoot() + |> Option.map (fun dotnetRoot -> + dotnetRoot + "packs" + "Microsoft.NETCore.App.Ref" + runtimeVersion + "ref" + "net" + rawVersion))) if Seq.isEmpty referenceAssembliesPaths then failwithf "Could not find referenced assemblies, please check installed SDK and runtime versions" else + if this.LogLevel.PrintVerbose then let paths = String.Join(",", referenceAssembliesPaths) Trace.tracefn $"Resolved referenced SDK paths: {paths}" - let referenceAssembliesPath = + let existingReferenceAssembliesPaths = referenceAssembliesPaths - |> List.tryFind (fun referenceAssembliesPath -> Directory.Exists referenceAssembliesPath) + |> List.collect (fun paths -> paths |> List.filter (fun path -> Directory.Exists path)) + + if this.LogLevel.PrintVerbose then + let paths = String.Join(",", existingReferenceAssembliesPaths) + Trace.tracefn $"Found referenced SDK paths: {paths}" + + let referenceAssembliesPath = existingReferenceAssembliesPaths |> List.tryHead match referenceAssembliesPath with | Some pathFound -> Directory.GetFiles(pathFound, "*.dll") |> Seq.toList diff --git a/src/test/Fake.DotNet.Cli.IntegrationTests/Main.fs b/src/test/Fake.DotNet.Cli.IntegrationTests/Main.fs index 7bacaeead17..e73db1dcad3 100644 --- a/src/test/Fake.DotNet.Cli.IntegrationTests/Main.fs +++ b/src/test/Fake.DotNet.Cli.IntegrationTests/Main.fs @@ -8,7 +8,7 @@ open System [] let main argv = - let config = defaultConfig |> ExpectoHelpers.addTimeout (TimeSpan.FromMinutes(20.)) + let config = defaultConfig |> ExpectoHelpers.addTimeout (TimeSpan.FromMinutes(30.)) Tests.runTestsInAssembly { config with From b3a7defba88add7ba7e89a4ee2cd303a01f7cf47 Mon Sep 17 00:00:00 2001 From: Tuomas Hietanen Date: Wed, 7 Aug 2024 09:00:16 +0100 Subject: [PATCH 2/4] Code review feedbacks implemeted --- src/app/Fake.Runtime/SdkAssemblyResolver.fs | 39 +++++++++++---------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/app/Fake.Runtime/SdkAssemblyResolver.fs b/src/app/Fake.Runtime/SdkAssemblyResolver.fs index 43b7f4f0e71..a01dc3b3afc 100644 --- a/src/app/Fake.Runtime/SdkAssemblyResolver.fs +++ b/src/app/Fake.Runtime/SdkAssemblyResolver.fs @@ -143,23 +143,28 @@ type SdkAssemblyResolver(logLevel: Trace.VerboseLevel) = if this.LogLevel.PrintVerbose then Trace.tracefn "Trying to resolve runtime version from network.." + let sdkSet = this.SdkVersionRaws |> Set.ofList + try - let sdkVersionReleases = - ProductCollection.GetAsync() - |> Async.AwaitTask - |> Async.RunSynchronously - |> List.ofSeq - |> List.filter (fun product -> - this.SdkVersionRaws - |> List.exists (fun raws -> product.ProductVersion.Equals raws)) - - sdkVersionReleases - |> List.collect (fun rel -> - rel.GetReleasesAsync() - |> Async.AwaitTask - |> Async.RunSynchronously - |> List.ofSeq) + task { + let! productCollection = ProductCollection.GetAsync() + + let sdkVersionReleases = + productCollection + |> Seq.filter (fun product -> sdkSet |> Set.exists (fun raws -> product.ProductVersion.Equals raws)) + + let! releases = + sdkVersionReleases + |> Seq.map (fun rel -> rel.GetReleasesAsync()) + |> System.Threading.Tasks.Task.WhenAll + + return releases |> Seq.collect (fun sdks -> sdks |> Seq.toList) + } + |> Async.AwaitTask + |> Async.RunSynchronously + |> Seq.toList |> Some + with ex -> Trace.traceError $"Could not get SDK runtime version from network due to: {ex.Message}" None @@ -192,9 +197,7 @@ type SdkAssemblyResolver(logLevel: Trace.VerboseLevel) = |> Option.orElseWith (this.TryResolveSdkRuntimeVersionFromCache) let sdkRelease (release: ProductRelease) = - release.Sdks - |> List.ofSeq - |> List.exists (fun sdk -> sdk.Version.Equals(version)) + release.Sdks |> Seq.exists (fun sdk -> sdk.Version.Equals(version)) match net60releases with | None -> [] From b7f46ff6dda0f4f1ae868166ecd9cfe4fee4fa8f Mon Sep 17 00:00:00 2001 From: Tuomas Hietanen Date: Fri, 9 Aug 2024 11:32:19 +0100 Subject: [PATCH 3/4] Assembly-resolver reporting improvements --- src/app/Fake.Runtime/SdkAssemblyResolver.fs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/app/Fake.Runtime/SdkAssemblyResolver.fs b/src/app/Fake.Runtime/SdkAssemblyResolver.fs index a01dc3b3afc..18fb4dad9d5 100644 --- a/src/app/Fake.Runtime/SdkAssemblyResolver.fs +++ b/src/app/Fake.Runtime/SdkAssemblyResolver.fs @@ -45,12 +45,22 @@ type SdkAssemblyResolver(logLevel: Trace.VerboseLevel) = member this.SdkVersionRaws = RuntimeAssemblyVersions member this.SdkVersions = - RuntimeAssemblyVersions |> List.map (fun v -> ReleaseVersion(v + ".0")) + RuntimeAssemblyVersions + |> List.map (fun v -> + if String.IsNullOrEmpty v || v = "\"\"" then + ReleaseVersion "6.0.0" + elif v.Contains "." then + ReleaseVersion(v + ".0") + else + ReleaseVersion(v + ".0.0")) member this.PaketFrameworkIdentifiers = this.SdkVersions |> List.map (fun thisSdk -> - FrameworkIdentifier.DotNetFramework(FrameworkVersion.TryParse(thisSdk.Major.ToString()).Value)) + match FrameworkVersion.TryParse(thisSdk.Major.ToString()) with + | Some v -> FrameworkIdentifier.DotNetFramework v + | None -> failwithf $"Paket: .NET not found: {thisSdk.Major.ToString()}") + member this.SdkVersionRaw = RuntimeAssemblyVersions |> Seq.head member this.SdkVersion = this.SdkVersions |> Seq.head @@ -221,7 +231,7 @@ type SdkAssemblyResolver(logLevel: Trace.VerboseLevel) = match this.GetProductReleasesForSdk sdkVersion with | [] -> failwithf - $"Could not find a suitable .NET 6 runtime version matching SDK version: {sdkVersion.ToString()} (You can also try setting environment variable FAKE_SDK_RESOLVER_CUSTOM_DOTNET_VERSION to e.g. 8.0 )" + $"Could not find a suitable .NET 6 runtime version matching SDK version: {sdkVersion.ToString()} (You can also try setting environment variable FAKE_SDK_RESOLVER_CUSTOM_DOTNET_VERSION to e.g. {sdkVersion.Major.ToString()}.0 )" | releases -> let versions = releases |> List.map (fun release -> release.Runtime.Version.ToString()) From f7eb260a663f398b2110ad000bfec05b3e1d2a90 Mon Sep 17 00:00:00 2001 From: Tuomas Hietanen Date: Mon, 19 Aug 2024 10:37:26 +0100 Subject: [PATCH 4/4] Readme update --- RELEASE_NOTES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index e3fd05ee50a..06075509a46 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,8 @@ # Release Notes +## 6.1.1 - 2024-08-19 +* BUGFIX: Assembly resolver to pick a found SDK instead of first SDK - https://github.com/fsprojects/FAKE/pull/2797/files + ## 6.1.0 - 2024-07-27 * BUGFIX: MSBuild.build adds a bad string at the end of properties, thanks @0x53A - https://github.com/fsprojects/FAKE/issues/2738 * BUGFIX: Allow setting Msbuild max cpu on Linux, thanks @TheAngryByrd - https://github.com/fsprojects/FAKE/pull/2772