This repo shows how to get a fully deterministic build using Source Link. Deterministic builds are important as they enable verification that the resulting binary was built from the specified source and provides traceability.
Deterministic builds require a property to be set to true during CI:
ContinuousIntegrationBuild
. These should not be enabled during local dev or the debugger
won't be able to find the local source files.
Therefore, you should use your CI system's variable to set them conditionally. For Azure Pipelines, it looks like this
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>
For GitHub Actions, the variable is GITHUB_ACTIONS
, so the result would be:
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup>
Or another option is to pass it to msbuild
or dotnet
with /p:ContinuousIntegrationBuild=true
Also EmbedUntrackedSources
should be enabled so that compiler-generated source, like AssemblyInfo, are included
in the PDB.
Add in your .csproj under <PropertyGroup>
:
<EmbedUntrackedSources>true</EmbedUntrackedSources>
Note that there's a workaround needed for many SDK's prior to 3.1.300. You'll need to add
a Directory.Build.targets
file with the following:
<Project>
<PropertyGroup>
<TargetFrameworkMonikerAssemblyAttributesPath>$([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)'))</TargetFrameworkMonikerAssemblyAttributesPath>
</PropertyGroup>
<ItemGroup>
<EmbeddedFiles Include="$(GeneratedAssemblyInfoFile)"/>
</ItemGroup>
</Project>
To see/test this locally, build with dotnet build /p:ContinuousIntegrationBuild=true
. After uploading to nuget.org, you could check it with NuGet Package Explorer: