sdk: dotnet build /p:ContinuousIntegrationBuild=true doesn't work

(I hope this is the correct place to raise this question/issue. apologies if it isn’t)

Issue

Trying to building a class library on a CI/CD server that is deterministic using the ContinuousIntegrationBuild=true property argument on the cli doesn’t seem to actually do this?

Assumption:

  • dotnet build should allow this msbuild property
  • I can build/confirm this on my localhost development machine for testing, before it is ‘pushed up’ to a CI server.

Steps to repo.

- mkdir deterministic-nuget
- cd deterministic-nuget
- dotnet new classlib
- dotnet build -c RELEASE /p:ContinuousIntegrationBuild=true -p:version=1.2.3-pre.1
- dotnet pack -c RELEASE --no-build -p:packageVersion=1.2.3-pre.1 -o C:\temp\nuget-testing\

now goto C:\temp\nuget-testing and double click on the .nupkg file that is there. NuGet Package Explorer opens up and this is what it looks like:

image

I’m not sure if this is an issue with NuGet or dotnet build CLI or NGPE?

Info

  • On my own windows 10 dev machine.
❯ dotnet --info
.NET SDK (reflecting any global.json):
 Version:   5.0.201
 Commit:    a09bd5c86c

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.19042
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\5.0.201\

Host (useful for support):
  Version: 5.0.4
  Commit:  f27d337295

.NET SDKs installed:
  2.2.207 [C:\Program Files\dotnet\sdk]
  3.1.406 [C:\Program Files\dotnet\sdk]
  5.0.100 [C:\Program Files\dotnet\sdk]
  5.0.201 [C:\Program Files\dotnet\sdk]

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 5
  • Comments: 33 (7 by maintainers)

Most upvoted comments

I noticed that paths were getting ‘normalized’ when I build a project with Microsoft.SourceLink.GitLab package installed and as soon as I uninstalled SourceLink, ContinuousIntegrationBuild=true has no effect. Didn’t have time to attempt debugging.

I’ve just hit this too on https://github.com/DamianEdwards/MinimalValidation. I haven’t been able to workaround it by being explicit when calling dotnet pack either.

I found this thread when trying to workout a similar issue to do with a TFS 2017 on premise Build that was not setting the specified properties. My initial suspicions were that the MSBuild that was being called was not passing the -p property settings through to a dependent project when being built. The VS solution only consisted of 2 projects. The main project and a test project.

The TFS build had the following dotnet command tasks:

  • dotnet restore
  • dotnet build
  • dotnet test
  • dotnet publish

The build task is where the properties were being set via the -p argument. I was using the project setting on the dotnet TFS task as **/*.csproj and I could see from the output that the test project was being picked up first and then the main project.

In the work folder of the build agent I could see that the test project assembly had the correct properties where as the main assembly did not. And as mentioned, it was my initial assumption that the test project was not passing the -p properties over to the main project when it was being built. So when the main project got built I could see that it did not actually do any building and was just using the previously built assemblies from the building of the test project. However after further investigation and several trial and error builds playing about with using the --no-incremental (clean) build option as well as having an explicit ordering by using separate TFS dotnet build tasks. I was still not getting any joy.

In the end I realised what was actually happening and it was the exact opposite of what I thought was going on. It was the final TFS dotnet publish tasks that was actually overwriting the earlier built assemblies that did have the correct properties being set. And not that the assemblies were not being built because they had already been built.

To fix this I simply added the --no-build argument to the TFS dotnet publish task which prevented the assemblies being rebuilt without the properties being set. The following is what I ended up with:

  • dotnet restore
  • dotnet build --no-restore -p:prop0=val0;prop1=val1;prop2=val2
  • dotnet test --no-restore --no-build
  • dotnet publish --no-restore --no-build

I hope this helps other people.

@iBrotNano, https://github.com/shouldly/shouldly/issues/795 has been filed about Shouldly changing those properties.

Ok so after some more tinkering, adding an explicit /p:Deterministic to the build, the build outputted the following error:

error : SourceRoot items must include at least one top-level (not nested) item when DeterministicSourcePaths is true

I then had to drop a Directory.Build.props into the root of my repository with the following contents

<Project>
  <ItemGroup>
    <SourceRoot Include="$(MSBuildThisFileDirectory)"/>
  </ItemGroup>
</Project>

and that + /p:ContinuousIntegrationBuild=true /p:Deterministic made it work.

EDIT: Welp, except i spoke too soon, the command line to csc now contains

/pathmap:"C:\Builds\Agent_Jones\_work\35\s\/=/_/,C:\Users\TFS\.nuget\packages\=/_1/,C:\Program Files\dotnet\sdk\NuGetFallbackFolder\=/_2/,"

so that looks good but stacktraces still start with C:\Builds\Agent_Jones\_work\35\s\sigh a problem for after the weekend

EDIT 2: Removed trailing / from the SourceRoot include which fixed it

I’ve narrowed this down to “seemingly nondeterministic behavior” with dotnet pack and when it decides it needs to rebuild the project. If I run dotnet test beforehand without the -p flag, and run dotnet pack afterwards with the -p flag, sometimes the NuGet package will be deterministic, and sometimes it won’t.

My workaround for now will be to have the workflow dotnet test with the default Debug config, and dotnet pack with the Release config, but I really think the proper default behavior for dotnet pack should be to always build from scratch if the CI flag is set – that’s literally the designed purpose of it: create deterministic builds.

I also have same issue - I’m using ContinuousIntegrationBuild but NGPE is showing that package is not deterministic. I have checked IL Spy and indeed it says: “This assembly was compiled using the /deterministic option.” so maybe it is a bug in NGPE