Cómo resolver el problema NETSDK1061 en Azure DevOps con un proyecto .NET Core 2.2 y una build de .NET Desktop
Voy a partir de un caso concreto, aunque puede darse en más casos.
Utilizando un pipeline para .NET Desktop y una solución con proyectos de .NET Framework y .NET Core.
A partir de este caso, al intentar llevar a cabo la integración continua de mi solución con Azure DevOps, aparece un mensaje de error NETSDK1061.
El mensaje exacto del error es algo similar a los siguiente:
src\ConsoleApp\ConsoleApp.csproj(0,0): Error : NETSDK1061: The project was restored using Microsoft.NETCore.App version 1.0.0, but with current settings, version 2.2.0 would be used instead. To resolve this issue, make sure the same settings are used for restore and for subsequent operations such as build or publish. Typically this issue can occur if the RuntimeIdentifier property is set during build or publish but not during restore. For more information, see https://aka.ms/dotnet-runtime-patch-selection.
src\Tests\MyLibrary.UnitTests\MyLibrary.UnitTests.csproj(0,0): Error : NETSDK1061: The project was restored using Microsoft.NETCore.App version 1.0.0, but with current settings, version 2.2.0 would be used instead. To resolve this issue, make sure the same settings are used for restore and for subsequent operations such as build or publish. Typically this issue can occur if the RuntimeIdentifier property is set during build or publish but not during restore. For more information, see https://aka.ms/dotnet-runtime-patch-selection.
Process ‘msbuild.exe’ exited with code ‘1’.
En mi caso concreto, parto de una solución con tres proyectos.
Un primer proyecto que corresponde con una librería .NET Framework 4.7.
Un segundo proyecto de tests de la librería en .NET Core 2.2.
Y un tercer y último proyecto que corresponde con una aplicación de consola, que consume la librería y que también está desarrollada en .NET Core 2.2.
Todo en un ambiente Windows.
La compilación en local funciona perfectamente.
Los tests en local también pasan de forma correcta, y nada parece estar mal.
Sin embargo, la integración continua con Azure DevOps devuelve en Azure Pipelines el error que indicaba anteriormente.
Del mensaje de error se desprende que éste se produce en los proyectos de .NET Core 2.2.
Lo primero que pensé es que había alguna referencia a .Net Core 1.0.0, pero aunque no tenía lógica me ví forzado en buscar alguna referencia.
Y efectivamente, después de rebuscar bien en los proyectos de .NET Core, no encontré ninguna referencia a .NET Core 1.0.0.
Confundido, también miré en los pasos del Pipeline de .NET Desktop que estaba utilizando {azure-pipelines.yml} y no encontré nada extraño (indico a continuación el contenido del script).
# .NET Desktop # Build and run tests for .NET Desktop or Windows classic desktop solutions. # Add steps that publish symbols, save build artifacts, and more: # https://docs.microsoft.com/azure/devops/pipelines/apps/windows/dot-net trigger: - master pool: vmImage: 'VS2017-Win2016' variables: solution: '**/*.sln' buildPlatform: 'Any CPU' buildConfiguration: 'Release' steps: - task: NuGetToolInstaller@0 - task: NuGetCommand@2 inputs: restoreSolution: '$(solution)' - task: VSBuild@1 inputs: solution: '$(solution)' platform: '$(buildPlatform)' configuration: '$(buildConfiguration)' - task: VSTest@2 inputs: platform: '$(buildPlatform)' configuration: '$(buildConfiguration)'
Investigando algo más sobre el problema y personalizando alguna tarea dentro del Pipeline de Azure DevOps, comprobé que la versión .NET Core 2.2 también estaba instalada.
Sin embargo, Azure Pipelines está devolviendo un error, así que la pregunta es ¿cómo resolver el problema? (si es que hay alguna forma).
Pues básicamente el problema se resuelve «forzando» la versión de .NET Core 2.2 a utilizar en los proyectos de .NET Core.
Valga un ejemplo más detallado para indicar cómo realizar esto.
Si el proyecto de consola tiene el siguiente código dentro del proyecto:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.2</TargetFramework> </PropertyGroup> <ItemGroup> <ProjectReference Include="..\MyLibrary\MyLibrary.csproj" /> </ItemGroup> </Project>
El código resultante que debería tener sería:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.2</TargetFramework> <RuntimeFrameworkVersion>2.2.0</RuntimeFrameworkVersion> <PlatformTarget>AnyCPU</PlatformTarget> </PropertyGroup> <ItemGroup> <PackageReference Update="Microsoft.NETCore.App" Version="2.2.0" /> <ProjectReference Include="..\MyLibrary\MyLibrary.csproj" /> </ItemGroup> </Project>
Nótese que he agregado aquí tanto RuntimeFrameworkVersion como PlatformTarget, y a su vez, la librería Microsoft.NETCore.App con su correspondiente versión.
Indudablemente, deberemos forzar esto según nuestras necesidades.
De la misma manera, el proyecto de Tests que tenía el siguiente código:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netcoreapp2.2</TargetFramework> <IsPackable>false</IsPackable> </PropertyGroup> <ItemGroup> <PackageReference Include="FluentAssertions" Version="5.6.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> <PackageReference Include="xunit" Version="2.4.0" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\MyLibrary\MyLibrary.csproj" /> </ItemGroup> </Project>
Quedará de la siguiente forma:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netcoreapp2.2</TargetFramework> <RuntimeFrameworkVersion>2.2.0</RuntimeFrameworkVersion> <PlatformTarget>AnyCPU</PlatformTarget> <IsPackable>false</IsPackable> </PropertyGroup> <ItemGroup> <PackageReference Update="Microsoft.NETCore.App" Version="2.2.0" /> <PackageReference Include="FluentAssertions" Version="5.6.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" /> <PackageReference Include="xunit" Version="2.4.0" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\MyLibrary\MyLibrary.csproj" /> </ItemGroup> </Project>
Si ahora ejecutamos el Pipeline de Azure DevOps, comprobaremos que funciona tal y cómo lo teníamos previsto.
Desconozco si Microsoft resolverá en un futuro cercano este problema o nos obligará a realizar este tipo de operaciones sobre el código. Microsoft por lo menos, ya que está al tanto del mismo, pero mientras tanto, espero que este workaround ayude y sirva a más de uno si se encuentra con este problema, problema por otro lado que buscando en Internet podrás encontrar que le ha ocurrido a más gente.
Para más información, te invito a visitar este enlace de Stackoverflow sobre el problema y este otro enlace sobre bugs y problemas con Azure DevOps sobre el mismo asunto que apunta a Stackoverflow a su vez.
Happy Coding!