Elena Canorea
Communications Lead
Como miembro encargado de mantener algunos proyectos de código abierto en Xabaril y que mucha gente utiliza, creo que es crucial ayudar a los desarrolladores a que puedan depurar el código fuente de nuestras librerías con el fin de facilitarles la vida a la hora de solucionar problemas y poder entender mejor su funcionamiento. Por este motivo, en Xabaril hemos decidido habilitar el soporte Source Link en nuestros proyectos.
Antes de continuar, quiero agradecer a Unai Zorrilla por mostrarme las bondades de Source Link y ayudarme a configurarlo en Balea.
Entorno de los ejemplos
Esta guía utiliza .NET Core 3.1 y Visual Studio 2019.
Source Link es una tecnología que permite a los desarrolladores depurar el código fuente de los paquetes NuGet. Herramientas como Visual Studio pueden aprovechar esta característica para depurar su código fuente como si se tratase de un proyecto local más y facilitar la solución de problemas al utilizar proyectos de código abierto.
El archivo dependencies.props permite definir las versiones de los paquetes NuGet en un solo lugar. Así evitamos problemas de consolidación de versiones entre los proyectos de una solución, mientras cada proyecto declara las dependencias que necesita.
<PropertyGroup Label="Package Dependencies">
<AspNetCoreVersion>3.1.3</AspNetCoreVersion>
<EntityFrameworkVersion>3.1.3</EntityFrameworkVersion>
</PropertyGroup>
En tu csproj tienes que definir qué dependencias vas a usar:
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="$(AspNetCoreVersion)" />
</ItemGroup>
De este modo, si el equipo de ASP.NET Core lanza una nueva versión, ya no es necesario pasar por todos los proyectos uno por uno actualizándola. Solo tendrás que actualizar la versión en dependencies.props y los proyectos que la referencien utilizarán esa versión.
Otro archivo con el que deberías estar familiarizado es Directory.Build.props, que facilita compartir metadatos comunes en toda la solución.
<Project>
<Import Project="build/dependencies.props" />
<PropertyGroup Label="Package information">
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<PackageProjectUrl>http://github.com/xabaril/Balea</PackageProjectUrl>
<RepositoryUrl>https://github.com/xabaril/Balea</RepositoryUrl>
<Authors>Xabaril Contributors</Authors>
<Company>Xabaril</Company>
</PropertyGroup>
</Project>
En la primera línea importamos el archivo dependencies.props y añadimos metadatos comunes para todos los proyectos, como la información de la licencia o la URL del proyecto.
Para habilitar Source Link en el proyecto, añade estas líneas a tu Directory.Build.props:
<!-- Publish the repository URL in the built .nupkg (in the NuSpec <Repository> element) -->
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<!-- Embed source files that are not tracked by the source control manager in the PDB -->
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<!-- Build symbol package (.snupkg) to distribute the PDB containing Source Link -->
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
Para los proyectos alojados en GitHub necesitarás referenciar el paquete de Source Link:
<ItemGroup>
<SourceRoot Include="$(MSBuildThisFileDirectory)/"/>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="$(MicrosoftSourceLinkGithub)">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
A continuación, tendrás que habilitar las compilaciones deterministas (deterministic builds). En este repositorio, Claire Novotny explica cómo funcionan y por qué son importantes.
Las compilaciones deterministas permiten verificar que el binario resultante se construyó a partir del código fuente especificado y aportan trazabilidad.
Añade lo siguiente a Directory.Build.props si estás usando GitHub Actions:
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>
Existe un problema conocido con el atributo EmbedUntrackedSources en SDK anteriores a 3.1.300. El artículo original se escribió utilizando el SDK 3.1.201.
Para ese entorno, añade un archivo Directory.Build.targets en el nivel de la solución con este contenido:
<Project>
<PropertyGroup>
<TargetFrameworkMonikerAssemblyAttributesPath>$([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)'))</TargetFrameworkMonikerAssemblyAttributesPath>
</PropertyGroup>
<ItemGroup>
<!-- https://github.com/dotnet/sourcelink/issues/572 -->
<EmbeddedFiles Include="$(GeneratedAssemblyInfoFile)"/>
</ItemGroup>
</Project>
Si quieres probar tus paquetes en una máquina local antes de publicarlos en el feed de NuGet, elimina temporalmente la condición de MSBuild para GitHub Actions:
<PropertyGroup>
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>
Ejecuta el siguiente comando para empaquetar tu proyecto:
dotnet pack <yoor_project>.csproj -c Release -o .\artifacts --include-symbols

Abre NuGet Package Explorer y selecciona Open a local package.

Localiza el paquete NuGet que acabas de generar.

Deberías ver Source Link y la compilación determinista ya verificados.

Antes de subir los cambios al repositorio, vuelve a añadir la condición para GitHub Actions que eliminaste durante la prueba local. Necesitarás una GitHub Action para publicar tus paquetes en el feed de NuGet.
Una vez publicado el paquete, abre de nuevo NuGet Package Explorer y selecciona Open a package from online feed.

Busca tu paquete de NuGet.

Si has seguido los pasos correctamente, el paquete debería ser válido y reflejar el último cambio de tu repositorio.

Por defecto, el servidor de símbolos de NuGet está desactivado. Visual Studio 2019 necesita descargar esos símbolos para trabajar con Source Link. Para activarlo, ve a Tools → Options → Debugging → Symbols.

Ve a Tools → Options → Debugging → General y desmarca Enable Just My Code.

Source Link está habilitado por defecto en Visual Studio 2019, pero el soporte para Source Server no lo está.

La opción Fallback to Git Credential Manager permite a las herramientas que utilizan Git Credential Manager usar Source Link con repositorios privados.
En este ejemplo he creado una aplicación Web API sencilla y he añadido los paquetes de Balea.

Ejecuta la aplicación web y pulsa F11 para entrar en el código de la librería.

La primera vez aparecerá una ventana que informa de que Source Link va a descargar el código de Internet, si no lo ha descargado previamente.

Una vez descargado el código fuente, ya podemos depurarlo desde Visual Studio.

En esta guía hemos visto cómo configurar Source Link en proyectos .NET y aprovechar esta característica desde Visual Studio. Para consultar un ejemplo completo, puedes revisar el repositorio de Balea.
Artículo original de referencia: Using Source Link in .NET projects and how to configure Visual Studio to use it.
Elena Canorea
Communications Lead