From a6f193910480f41760a8008ff68a61fd095063e7 Mon Sep 17 00:00:00 2001 From: Adam Boniecki <20281641+abonie@users.noreply.github.com> Date: Tue, 4 Aug 2026 20:23:07 +0200 Subject: [PATCH 1/3] Bump Newtonsoft version restored in fsi tests --- .../CompilerOptions/fsi/FsiCliTests.fs | 22 +++++++++++++++---- .../FSharp.Compiler.ComponentTests.fsproj | 10 +++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs index dbb08a42edb..5f276768c28 100644 --- a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs @@ -85,10 +85,24 @@ module FsiCliTests = finally try System.IO.File.Delete(scriptPath) with _ -> () + // The FSI #r "nuget:" restore below must request a package version that is guaranteed to be in + // the offline restore cache on the internal signed build (which cannot restore online). Central + // package management + transitive pinning means only the centrally-pinned version (eng/Packages.props) + // is ever restored into that cache, and it changes whenever the pin is bumped. Rather than hardcode + // a version that would silently drift, read the exact pinned version baked into this test assembly + // at build time via AssemblyMetadata (see FSharp.Compiler.ComponentTests.fsproj). + let private centralNewtonsoftJsonVersion = + System.Reflection.Assembly.GetExecutingAssembly().GetCustomAttributes(typeof, false) + |> Array.tryPick (fun a -> + let m = a :?> System.Reflection.AssemblyMetadataAttribute + if m.Key = "NewtonsoftJsonCentralVersion" && not (System.String.IsNullOrWhiteSpace m.Value) then Some m.Value else None) + |> Option.defaultWith (fun () -> + failwith "AssemblyMetadata 'NewtonsoftJsonCentralVersion' is missing. It should be emitted by FSharp.Compiler.ComponentTests.fsproj from the central Newtonsoft.Json PackageVersion.") + [] let ``FSI quiet mode suppresses NuGet restore output from stdout`` () = - let script = """ -#r "nuget: Newtonsoft.Json, 13.0.3" + let script = $""" +#r "nuget: Newtonsoft.Json, {centralNewtonsoftJsonVersion}" printfn "RESULT_MARKER_18086" """ let result = runFsiScript ["--quiet"] script @@ -100,8 +114,8 @@ printfn "RESULT_MARKER_18086" [] let ``FSI default (non-quiet) mode still evaluates script and prints user output`` () = - let script = """ -#r "nuget: Newtonsoft.Json, 13.0.3" + let script = $""" +#r "nuget: Newtonsoft.Json, {centralNewtonsoftJsonVersion}" printfn "RESULT_MARKER_18086_DEFAULT" """ let result = runFsiScript [] script diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 9552df0463c..e9e58f5ab36 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -562,5 +562,15 @@ + + + @(PackageVersion->WithMetadataValue('Identity','Newtonsoft.Json')->'%(Version)') + + + + From c551b056fb3f47698cac8af3143a57b314d9ad02 Mon Sep 17 00:00:00 2001 From: Adam Boniecki <20281641+abonie@users.noreply.github.com> Date: Wed, 5 Aug 2026 09:46:43 +0200 Subject: [PATCH 2/3] Switch from Newtonsoft to FsCheck for #r test --- .../CompilerOptions/fsi/FsiCliTests.fs | 16 ++++++++++------ .../FSharp.Compiler.ComponentTests.fsproj | 16 ++++++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs index 5f276768c28..7d40f811058 100644 --- a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs @@ -90,19 +90,23 @@ module FsiCliTests = // package management + transitive pinning means only the centrally-pinned version (eng/Packages.props) // is ever restored into that cache, and it changes whenever the pin is bumped. Rather than hardcode // a version that would silently drift, read the exact pinned version baked into this test assembly - // at build time via AssemblyMetadata (see FSharp.Compiler.ComponentTests.fsproj). - let private centralNewtonsoftJsonVersion = + // at build time via AssemblyMetadata (see FSharp.Compiler.ComponentTests.fsproj). The package id + // (FsCheck) is kept in sync with that project; any centrally-pinned standalone package would do. + [] + let private restoreTestPackageId = "FsCheck" + + let private restoreTestPackageVersion = System.Reflection.Assembly.GetExecutingAssembly().GetCustomAttributes(typeof, false) |> Array.tryPick (fun a -> let m = a :?> System.Reflection.AssemblyMetadataAttribute - if m.Key = "NewtonsoftJsonCentralVersion" && not (System.String.IsNullOrWhiteSpace m.Value) then Some m.Value else None) + if m.Key = "FsiRestoreTestPackageVersion" && not (System.String.IsNullOrWhiteSpace m.Value) then Some m.Value else None) |> Option.defaultWith (fun () -> - failwith "AssemblyMetadata 'NewtonsoftJsonCentralVersion' is missing. It should be emitted by FSharp.Compiler.ComponentTests.fsproj from the central Newtonsoft.Json PackageVersion.") + failwith "AssemblyMetadata 'FsiRestoreTestPackageVersion' is missing. It should be emitted by FSharp.Compiler.ComponentTests.fsproj from the central FsCheck PackageVersion.") [] let ``FSI quiet mode suppresses NuGet restore output from stdout`` () = let script = $""" -#r "nuget: Newtonsoft.Json, {centralNewtonsoftJsonVersion}" +#r "nuget: {restoreTestPackageId}, {restoreTestPackageVersion}" printfn "RESULT_MARKER_18086" """ let result = runFsiScript ["--quiet"] script @@ -115,7 +119,7 @@ printfn "RESULT_MARKER_18086" [] let ``FSI default (non-quiet) mode still evaluates script and prints user output`` () = let script = $""" -#r "nuget: Newtonsoft.Json, {centralNewtonsoftJsonVersion}" +#r "nuget: {restoreTestPackageId}, {restoreTestPackageVersion}" printfn "RESULT_MARKER_18086_DEFAULT" """ let result = runFsiScript [] script diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index e9e58f5ab36..827e5ff96da 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -562,15 +562,19 @@ - + - @(PackageVersion->WithMetadataValue('Identity','Newtonsoft.Json')->'%(Version)') + @(PackageVersion->WithMetadataValue('Identity','FsCheck')->'%(Version)') - + From 45e12726b9cf4fb45a9f13e652d2e1e8d32db76d Mon Sep 17 00:00:00 2001 From: Adam Boniecki <20281641+abonie@users.noreply.github.com> Date: Wed, 5 Aug 2026 10:21:28 +0200 Subject: [PATCH 3/3] Make FSI nuget-restore tests robust to central package management The two FsiCliTests that exercise `#r "nuget:"` restore hardcoded Newtonsoft.Json 13.0.3. After central package management with transitive pinning was enabled, only the centrally-pinned version is restored into the offline cache used by the internal signed build, so requesting 13.0.3 failed there (version-resolution NUxxxx diagnostics on stdout). Instead of hardcoding a version (which would silently drift on every central bump), bake the centrally-pinned version into the test assembly via AssemblyMetadata and read it at runtime. Switch the target package from Newtonsoft.Json (a removal candidate) to MessagePack, which is actively maintained, published on public nuget.org (so online public CI restore works) and centrally pinned + restored transitively by the product (so it is present in the internal offline cache). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: df9d1550-25ab-4466-ae43-8c7f106f4e49 --- .../CompilerOptions/fsi/FsiCliTests.fs | 6 +++--- .../FSharp.Compiler.ComponentTests.fsproj | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs index 7d40f811058..2f96d57d663 100644 --- a/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/CompilerOptions/fsi/FsiCliTests.fs @@ -91,9 +91,9 @@ module FsiCliTests = // is ever restored into that cache, and it changes whenever the pin is bumped. Rather than hardcode // a version that would silently drift, read the exact pinned version baked into this test assembly // at build time via AssemblyMetadata (see FSharp.Compiler.ComponentTests.fsproj). The package id - // (FsCheck) is kept in sync with that project; any centrally-pinned standalone package would do. + // (MessagePack) is kept in sync with that project; any centrally-pinned standalone package would do. [] - let private restoreTestPackageId = "FsCheck" + let private restoreTestPackageId = "MessagePack" let private restoreTestPackageVersion = System.Reflection.Assembly.GetExecutingAssembly().GetCustomAttributes(typeof, false) @@ -101,7 +101,7 @@ module FsiCliTests = let m = a :?> System.Reflection.AssemblyMetadataAttribute if m.Key = "FsiRestoreTestPackageVersion" && not (System.String.IsNullOrWhiteSpace m.Value) then Some m.Value else None) |> Option.defaultWith (fun () -> - failwith "AssemblyMetadata 'FsiRestoreTestPackageVersion' is missing. It should be emitted by FSharp.Compiler.ComponentTests.fsproj from the central FsCheck PackageVersion.") + failwith "AssemblyMetadata 'FsiRestoreTestPackageVersion' is missing. It should be emitted by FSharp.Compiler.ComponentTests.fsproj from the central MessagePack PackageVersion.") [] let ``FSI quiet mode suppresses NuGet restore output from stdout`` () = diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj index 827e5ff96da..476b903efcf 100644 --- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj +++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj @@ -567,11 +567,12 @@ requested version must be one that is already in the restore cache. Under central package management with transitive pinning, that is exactly the centrally-pinned version (eng/Packages.props). Bake that version into the test assembly so the test can request it at - runtime with no manual sync when the central pin is bumped. FsCheck is used (rather than a - general-purpose JSON package) because it is an F#-owned standalone leaf library that is centrally - pinned and restored by the build; keep the package id here in sync with the id in FsiCliTests.fs. --> + runtime with no manual sync when the central pin is bumped. MessagePack is used (rather than a + general-purpose JSON package) because it is an actively-maintained, non-system standalone library + that is centrally pinned and restored transitively by the product (StreamJsonRpc); keep the + package id here in sync with the id in FsiCliTests.fs. --> - @(PackageVersion->WithMetadataValue('Identity','FsCheck')->'%(Version)') + @(PackageVersion->WithMetadataValue('Identity','MessagePack')->'%(Version)')