Upgrade C# Protobuf projects to .NET 8.0. This change updates the target frameworks for various C# projects within Protobuf to .NET 8.0, while also maintaining netstandard2.0 for the core library. Support for older frameworks like net45, net50, and netstandard1.1 has been removed. This updates our project to match our support policy in https://github.com/google/oss-policies-info/blob/main/foundational-dotnet-support-matrix.md which actually dropped support for net45, net50, etc long ago. PiperOrigin-RevId: 914580666
diff --git a/.github/workflows/test_csharp.yml b/.github/workflows/test_csharp.yml index 6e9331b..de8357f 100644 --- a/.github/workflows/test_csharp.yml +++ b/.github/workflows/test_csharp.yml
@@ -27,7 +27,7 @@ - name: Run tests uses: protocolbuffers/protobuf-ci/docker@v5 with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/csharp:8.0.1-3.1.415-6.0.100-b77fdae6d4771789dfc66a56bf8d806354e8011a + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/csharp:9.0.0-3.1.415-8.0.100-05b57cb3d33f45f689c1dace146b6b9619d78872 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} entrypoint: /bin/bash command: >- @@ -35,7 +35,7 @@ cd csharp && dotnet restore src/Google.Protobuf.sln && dotnet build -c Release src/Google.Protobuf.sln && - dotnet test -c Release -f net6.0 src/Google.Protobuf.Test/Google.Protobuf.Test.csproj" + dotnet test -c Release -f net8.0 src/Google.Protobuf.Test/Google.Protobuf.Test.csproj" - name: Clear bazel between docker instances run: sudo rm -rf _build .repository-cache @@ -43,10 +43,10 @@ - name: Run conformance tests uses: protocolbuffers/protobuf-ci/bazel-docker@v5 with: - image: us-docker.pkg.dev/protobuf-build/containers/test/linux/csharp:8.0.1-3.1.415-6.0.100-b77fdae6d4771789dfc66a56bf8d806354e8011a + image: us-docker.pkg.dev/protobuf-build/containers/test/linux/csharp:9.0.0-3.1.415-8.0.100-05b57cb3d33f45f689c1dace146b6b9619d78872 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} bazel-cache: csharp_linux - bazel: test //csharp:conformance_test --action_env=DOTNET_CLI_TELEMETRY_OPTOUT=1 --test_env=DOTNET_CLI_HOME=/home/bazel + bazel: test //csharp:conformance_test --action_env=PATH --action_env=DOTNET_CLI_TELEMETRY_OPTOUT=1 --test_env=DOTNET_CLI_HOME=/home/bazel windows: name: Windows @@ -60,12 +60,12 @@ - name: Setup dotnet uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0 with: - dotnet-version: '6.0.x' + dotnet-version: '8.0.x' - name: Run tests uses: protocolbuffers/protobuf-ci/bash@v5 with: - bazel-version: 8.0.1 + bazel-version: 9.0.0 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} command: | dotnet build csharp/src/Google.Protobuf.sln @@ -85,13 +85,13 @@ # (we want to avoid references to ~/.nuget that won't be available in the subsequent docker run) uses: protocolbuffers/protobuf-ci/docker@v5 with: - image: mcr.microsoft.com/dotnet/sdk:6.0.100-bullseye-slim + image: mcr.microsoft.com/dotnet/sdk:8.0.100-bookworm-slim credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} command: >- /bin/bash -cex ' DOTNET_CLI_TELEMETRY_OPTOUT=true DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true - dotnet publish -c Release -f net6.0 /workspace/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj' + dotnet publish -c Release -f net8.0 /workspace/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj' - name: Use an actual aarch64 docker image to run protobuf C# tests with an emulator # "dotnet vstest" allows running tests from a pre-built project. @@ -102,11 +102,11 @@ # we just run map the user's home to a throwaway temporary directory uses: protocolbuffers/protobuf-ci/docker@v5 with: - image: mcr.microsoft.com/dotnet/sdk:6.0.100-bullseye-slim-arm64v8 + image: mcr.microsoft.com/dotnet/sdk:8.0.100-bookworm-slim-arm64v8 skip-staleness-check: true credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} command: >- /bin/bash -cex ' DOTNET_CLI_TELEMETRY_OPTOUT=true DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true - dotnet vstest /workspace/csharp/src/Google.Protobuf.Test/bin/Release/net6.0/publish/Google.Protobuf.Test.dll' + dotnet vstest /workspace/csharp/src/Google.Protobuf.Test/bin/Release/net8.0/publish/Google.Protobuf.Test.dll'
diff --git a/appveyor.bat b/appveyor.bat index 22cf1e8..b970275 100644 --- a/appveyor.bat +++ b/appveyor.bat
@@ -38,8 +38,7 @@ dotnet build -c %configuration% || goto error echo Testing C# -dotnet test -c %configuration% -f net6.0 Google.Protobuf.Test\Google.Protobuf.Test.csproj || goto error -dotnet test -c %configuration% -f net462 Google.Protobuf.Test\Google.Protobuf.Test.csproj || goto error +dotnet test -c %configuration% -f net8.0 Google.Protobuf.Test\Google.Protobuf.Test.csproj || goto error goto :EOF
diff --git a/csharp/BUILD.bazel b/csharp/BUILD.bazel index 8f4371d..9b75619 100644 --- a/csharp/BUILD.bazel +++ b/csharp/BUILD.bazel
@@ -103,7 +103,7 @@ pushd `dirname $(location src/Google.Protobuf.sln)`/.. dotnet restore src/Google.Protobuf.sln dotnet build -c Release src/Google.Protobuf.sln - dotnet test -c Release -f net6.0 src/Google.Protobuf.Test/Google.Protobuf.Test.csproj + dotnet test -c Release -f net8.0 src/Google.Protobuf.Test/Google.Protobuf.Test.csproj popd """, )
diff --git a/csharp/buildall.sh b/csharp/buildall.sh index c9525eb..fa07327 100755 --- a/csharp/buildall.sh +++ b/csharp/buildall.sh
@@ -10,8 +10,8 @@ dotnet build -c $CONFIG $SRC/Google.Protobuf.sln echo Running tests. -# Only test net6.0, which uses the .NET runtime. +# Only test net8.0, which uses the .NET runtime. # If we want to test the .NET 4.5 version separately, we could # run Mono explicitly. However, we don't have any differences between # the .NET 4.5 and netstandard2.1 assemblies. -dotnet test -c $CONFIG -f net6.0 $SRC/Google.Protobuf.Test/Google.Protobuf.Test.csproj +dotnet test -c $CONFIG -f net8.0 $SRC/Google.Protobuf.Test/Google.Protobuf.Test.csproj
diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj index 59edf2c..a5a7d48 100644 --- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj +++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
@@ -1,8 +1,8 @@ -<Project Sdk="Microsoft.NET.Sdk"> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> - <TargetFrameworks>net462;net6.0</TargetFrameworks> + <TargetFrameworks>net8.0</TargetFrameworks> <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile> <SignAssembly>true</SignAssembly> <IsPackable>False</IsPackable>
diff --git a/csharp/compatibility_tests/v3.0.0/test.sh b/csharp/compatibility_tests/v3.0.0/test.sh index ddf844a..341f219 100755 --- a/csharp/compatibility_tests/v3.0.0/test.sh +++ b/csharp/compatibility_tests/v3.0.0/test.sh
@@ -22,7 +22,7 @@ dotnet restore src/Google.Protobuf.Test/Google.Protobuf.Test.csproj dotnet build -c Release src/Google.Protobuf/Google.Protobuf.csproj dotnet build -c Release src/Google.Protobuf.Test/Google.Protobuf.Test.csproj - dotnet run -c Release -f net6.0 -p src/Google.Protobuf.Test/Google.Protobuf.Test.csproj + dotnet run -c Release -f net8.0 -p src/Google.Protobuf.Test/Google.Protobuf.Test.csproj } set -ex
diff --git a/csharp/src/AddressBook/AddressBook.csproj b/csharp/src/AddressBook/AddressBook.csproj index a50fc47..c403087 100644 --- a/csharp/src/AddressBook/AddressBook.csproj +++ b/csharp/src/AddressBook/AddressBook.csproj
@@ -1,7 +1,7 @@ -<Project Sdk="Microsoft.NET.Sdk"> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net6.0</TargetFramework> + <TargetFramework>net8.0</TargetFramework> <OutputType>Exe</OutputType> <StartupObject>Google.Protobuf.Examples.AddressBook.Program</StartupObject> <IsPackable>False</IsPackable>
diff --git a/csharp/src/Google.Protobuf.Conformance/BUILD.bazel b/csharp/src/Google.Protobuf.Conformance/BUILD.bazel index 81db8b5..93298df 100644 --- a/csharp/src/Google.Protobuf.Conformance/BUILD.bazel +++ b/csharp/src/Google.Protobuf.Conformance/BUILD.bazel
@@ -58,7 +58,7 @@ SRCDIR=$$(dirname $(location :Program.cs)) cp $(location //conformance:conformance_csharp_proto) $$SRCDIR DOTNET_CLI_HOME=/tmp ./$(location :build_conformance_test) - cp -r $$SRCDIR/bin/Release/net6.0/* $(RULEDIR) + cp -r $$SRCDIR/bin/Release/net8.0/* $(RULEDIR) """, tools = [":build_conformance_test"], visibility = ["//visibility:private"],
diff --git a/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj b/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj index 3bcfb35..f4da20c 100644 --- a/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj +++ b/csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj
@@ -1,7 +1,7 @@ -<Project Sdk="Microsoft.NET.Sdk"> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net6.0</TargetFramework> + <TargetFramework>net8.0</TargetFramework> <OutputType>Exe</OutputType> <IsPackable>False</IsPackable> </PropertyGroup>
diff --git a/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj b/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj index 475402b..8220584 100644 --- a/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj +++ b/csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj
@@ -1,7 +1,7 @@ -<Project Sdk="Microsoft.NET.Sdk"> +<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFramework>net6.0</TargetFramework> + <TargetFramework>net8.0</TargetFramework> <OutputType>Exe</OutputType> <IsPackable>False</IsPackable> </PropertyGroup>
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/Google.Protobuf.Test.TestProtos.csproj b/csharp/src/Google.Protobuf.Test.TestProtos/Google.Protobuf.Test.TestProtos.csproj index 1d21193..a3b44db 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/Google.Protobuf.Test.TestProtos.csproj +++ b/csharp/src/Google.Protobuf.Test.TestProtos/Google.Protobuf.Test.TestProtos.csproj
@@ -6,7 +6,7 @@ and without the internal visibility from the test project (all of which have caused issues in the past). --> <PropertyGroup> - <TargetFrameworks>net462;netstandard2.0</TargetFrameworks> + <TargetFrameworks>net8.0;netstandard2.0</TargetFrameworks> <LangVersion>10.0</LangVersion> <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile> <SignAssembly>true</SignAssembly>
diff --git a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj index cbdc13f..cc2f758 100644 --- a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj +++ b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
@@ -1,7 +1,7 @@ <Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> - <TargetFrameworks>net462;net6.0</TargetFrameworks> + <TargetFrameworks>net8.0</TargetFrameworks> <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile> <SignAssembly>true</SignAssembly> <IsPackable>False</IsPackable>
diff --git a/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs b/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs deleted file mode 100644 index f15da61..0000000 --- a/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs +++ /dev/null
@@ -1,98 +0,0 @@ -#region Copyright notice and license -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file or at -// https://developers.google.com/open-source/licenses/bsd -#endregion - -using NUnit.Framework; -using System.Diagnostics; -using System; -using System.Reflection; -using System.IO; - -namespace Google.Protobuf -{ - public class RefStructCompatibilityTest - { - /// <summary> - /// Checks that the generated code can be compiler with an old C# compiler. - /// The reason why this test is needed is that even though dotnet SDK projects allow to set LangVersion, - /// this setting doesn't accurately simulate compilation with an actual old pre-roslyn C# compiler. - /// For instance, the "ref struct" types are only supported by C# 7.2 and higher, but even if - /// LangVersion is set low, the roslyn compiler still understands the concept of ref struct - /// and silently accepts them. Therefore we try to build the generated code with an actual old C# compiler - /// to be able to catch these sort of compatibility problems. - /// </summary> - [Test] - public void GeneratedCodeCompilesWithOldCsharpCompiler() - { - if (Environment.OSVersion.Platform != PlatformID.Win32NT) - { - // This tests needs old C# compiler which is only available on Windows. Skipping it on all other platforms. - return; - } - - var currentAssemblyDir = Path.GetDirectoryName(typeof(RefStructCompatibilityTest).GetTypeInfo().Assembly.Location); - var testProtosProjectDir = Path.GetFullPath(Path.Combine(currentAssemblyDir, "..", "..", "..", "..", "Google.Protobuf.Test.TestProtos")); - var testProtosOutputDir = (currentAssemblyDir.Contains("bin/Debug/") || currentAssemblyDir.Contains("bin\\Debug\\")) ? "bin\\Debug\\net462" : "bin\\Release\\net462"; - - // If "ref struct" types are used in the generated code, compilation with an old compiler will fail with the following error: - // "XYZ is obsolete: 'Types with embedded references are not supported in this version of your compiler.'" - // We build the code with GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE to avoid the use of ref struct in the generated code. - var compatibilityFlag = "-define:GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE"; - var sources = "*.cs"; // the generated sources from the TestProtos project - // We suppress CS1691, which flags a warning for the generated line of - // #pragma warning disable 1591, 0612, 3021, 8981 - // because CS8981 is unknown to this version of the compiler. - var args = $"-langversion:3 -nologo -nowarn:1691 -target:library {compatibilityFlag} -reference:{testProtosOutputDir}\\Google.Protobuf.dll -out:{testProtosOutputDir}\\TestProtos.RefStructCompatibilityTest.OldCompiler.dll {sources}"; - RunOldCsharpCompilerAndCheckSuccess(args, testProtosProjectDir); - } - - /// <summary> - /// Invoke an old C# compiler in a subprocess and check it finished successful. - /// </summary> - /// <param name="args"></param> - /// <param name="workingDirectory"></param> - private void RunOldCsharpCompilerAndCheckSuccess(string args, string workingDirectory) - { - using var process = new Process(); - - // Get the path to the old C# 5 compiler from .NET framework. This approach is not 100% reliable, but works on most machines. - // Alternative way of getting the framework path is System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() - // but it only works with the net45 target. - var oldCsharpCompilerPath = Path.Combine(Environment.GetEnvironmentVariable("WINDIR"), "Microsoft.NET", "Framework", "v4.0.30319", "csc.exe"); - process.StartInfo.FileName = oldCsharpCompilerPath; - process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.RedirectStandardError = true; - process.StartInfo.UseShellExecute = false; - process.StartInfo.Arguments = args; - process.StartInfo.WorkingDirectory = workingDirectory; - - process.OutputDataReceived += (sender, e) => - { - if (e.Data != null) - { - Console.WriteLine(e.Data); - } - }; - process.ErrorDataReceived += (sender, e) => - { - if (e.Data != null) - { - Console.WriteLine(e.Data); - } - }; - - process.Start(); - - process.BeginErrorReadLine(); - process.BeginOutputReadLine(); - - process.WaitForExit(); - Assert.AreEqual(0, process.ExitCode); - } - } -} \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs index de9671f..bd4141e 100644 --- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs +++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
@@ -712,11 +712,7 @@ // 2. validate that size of csharp element T is matching the size of protobuf wire size // NOTE: cannot use bool with this span because csharp marshal it as 4 bytes if (BitConverter.IsLittleEndian && (codec.FixedSize > 0 && -#if GOOGLE_PROTOBUF_SUPPORT_GENERIC_SIZEOF Marshal.SizeOf<T>() -#else - Marshal.SizeOf(typeof(T)) -#endif == codec.FixedSize)) { handle = GCHandle.Alloc(array, GCHandleType.Pinned);
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj index bf0b175..b7ec796 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj +++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
@@ -8,12 +8,12 @@ <VersionPrefix>3.36.0</VersionPrefix> <LangVersion>10.0</LangVersion> <Authors>Google Inc.</Authors> - <TargetFrameworks>netstandard1.1;netstandard2.0;net45;net50</TargetFrameworks> + <TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks> <GenerateDocumentationFile>true</GenerateDocumentationFile> <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile> <SignAssembly>true</SignAssembly> <PackageTags>Protocol;Buffers;Binary;Serialization;Format;Google;proto;proto3</PackageTags> - <PackageReleaseNotes>C# proto3 support</PackageReleaseNotes> + <PackageReleaseNotes>C# proto support</PackageReleaseNotes> <PackageProjectUrl>https://github.com/protocolbuffers/protobuf</PackageProjectUrl> <PackageLicenseExpression>BSD-3-Clause</PackageLicenseExpression> <RepositoryType>git</RepositoryType> @@ -28,12 +28,9 @@ <NoWarn>$(NoWarn);NETSDK1195;NETSDK1210</NoWarn> </PropertyGroup> - <PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' "> - <DefineConstants>$(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_FAST_STRING;GOOGLE_PROTOBUF_SUPPORT_GENERIC_SIZEOF</DefineConstants> - </PropertyGroup> - <PropertyGroup Condition=" '$(TargetFramework)' == 'net50' "> - <DefineConstants>$(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_FAST_STRING;GOOGLE_PROTOBUF_SUPPORT_GENERIC_SIZEOF;GOOGLE_PROTOBUF_SIMD</DefineConstants> + <PropertyGroup Condition=" '$(TargetFramework)' == 'net8.0' "> + <DefineConstants>$(DefineConstants);GOOGLE_PROTOBUF_SIMD</DefineConstants> </PropertyGroup> <ItemGroup> @@ -42,14 +39,9 @@ <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" PrivateAssets="All" Version="1.0.0"/> </ItemGroup> - <ItemGroup Condition=" '$(TargetFramework)' == 'net45' OR '$(TargetFramework)' == 'netstandard1.1' "> - <!-- TODO --> - <PackageReference Include="System.Memory" Version="4.5.3"/> - </ItemGroup> - <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' "> <PackageReference Include="System.Memory" Version="4.5.3"/> - <!-- Needed for netcoreapp3.1 to work correctly. .NET is not able to load the assembly without this --> + <!-- Needed fotr netcoreapp3.1 to work correctly. .NET is not able to load the assembly without this --> <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.2"/> </ItemGroup>
diff --git a/csharp/src/Google.Protobuf/ParsingPrimitives.cs b/csharp/src/Google.Protobuf/ParsingPrimitives.cs index a877f38..bbbc93a 100644 --- a/csharp/src/Google.Protobuf/ParsingPrimitives.cs +++ b/csharp/src/Google.Protobuf/ParsingPrimitives.cs
@@ -570,7 +570,6 @@ throw InvalidProtocolBufferException.NegativeSize(); } -#if GOOGLE_PROTOBUF_SUPPORT_FAST_STRING if (length <= state.bufferSize - state.bufferPos) { // Fast path: all bytes to decode appear in the same span. @@ -595,7 +594,6 @@ state.bufferPos += length; return value; } -#endif return ReadStringSlow(ref buffer, ref state, length); } @@ -607,7 +605,6 @@ { ValidateCurrentLimit(ref buffer, ref state, length); -#if GOOGLE_PROTOBUF_SUPPORT_FAST_STRING if (IsDataAvailable(ref state, length)) { // Read string data into a temporary buffer, either stackalloc'ed or from ArrayPool @@ -649,7 +646,6 @@ } } } -#endif // Slow path: Build a byte array first then copy it. // This will be called when reading from a Stream because we don't know the length of the stream,
diff --git a/global.json b/global.json index ade0252..c19a2e0 100644 --- a/global.json +++ b/global.json
@@ -1,6 +1,6 @@ -{ +{ "sdk": { - "version": "6.0.100", + "version": "8.0.100", "rollForward": "latestMinor" } }