dotnet / dotnet/sdk

Provide guidance around an idiomatic way to configure "official" / CI builds

Open
#46,743 1 comment 0 reactions 0 assignees View on GitHub
Area-NetSDK untriaged
Dominant language
C#
Stars
3.2k
Forks
1.3k
PR merge metrics
PR metrics pending

Description

## Summary

There doesn't seem to be a standard practice or idiomatic way to specify an "official" build that optional / expensive operations should key off of. Some common types of operations that would benefit from this type of practice:

- Setting version numbers
- Enabling / disabling NuGet lock mode (see https://devblogs.microsoft.com/nuget/enable-repeatable-package-restores-using-a-lock-file/)
- Setting PDB info (e.g. deterministic source paths, embedding, etc.)
- Configuring how pedantic tools should be in regard to warning levels, warnings as errors, etc.

Different codebases create drastically different methods for configuring similar sets of properties, which makes new developer onboarding more difficult. My goal with this issue is to reach consensus and provide guidance for the ecosystem to increase discoverability.

## Example scenario

To ground the conversation, I'll use the common example of enabling warnings as errors when doing an official build. I'm picking this example because it is both one that teams often set, and it's a common source of contention for developers. Some developers want it off while hacking around code; some developers want it on to prevent surprises in CI. @jaredpar has a good summary of the tradeoffs here: https://github.com/dotnet/runtime/issues/78414#issuecomment-1783408373.

> [!NOTE]
> Specifically for code analysis there's https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#optimizeimplicitlytriggeredbuild, which would let Visual Studio handle the most common case here, however:
>
> 1. it is VS-centric
> 2. it doesn't appear to be open to extension
> 3. It can be confusing for users, as a build may pass and then fail with no user changes

Based on my experience and a quick review of public GitHub code, here's a sampling of the options folks use today.

## Configuration Options

### Configuration == Release

```xml

true

```

This one is probably the oldest and most straightforward to understand. However, most devs operate in Debug most of the time, and often CI pipelines run CI tests in Debug in addition to Release.

#### Pros

- Simple to understand

#### Cons

- Only applies to release
- Can lead to bit rot in Debug
- Ties together unrelated concerns

### BuildingInVisualStudio

```xml

true

```

Another one I've seen occasionally is using the BuildingInVisualStudio property as a proxy for "is in dev inner loop". However, it _only_ works for developers using Visual Studio. Additionally, setting this property on the command line to reproduce CI-only issues is likely to break other things.

#### Pros

- Automatic proxy for the dev's inner loop

#### Cons

- VS-centric
- Unpopular (only 4 hits in GitHub)

### ContinuousIntegrationBuild

```xml

true

```

ContinuousIntegrationBuild is provided by the [dotnet/reproducible-builds: Contains the DotNet.ReproducibleBuilds package](https://github.com/dotnet/reproducible-builds) package, and is consumed by some tools like Source Link, and also mentioned in a few blog posts. The RPB implementation specifically has the issue of being a computed property, requiring consumption in a .targets file, which is confusing for users.

#### Pros

- Relatively popular - 3k hits -- [Code search results](https://github.com/search?q=%22%24%28ContinuousIntegrationBuild%29%22+language%3AXML&type=code)
- Used by some dotnet projects like SourceLink and official blog posts

#### Cons

- Slightly awkward name
- Requires manual plumbing or adopting RPB

## Next steps

Where do we go from here? Ideally we could answer these questions:

- Are there other options we should consider?
- Are there any other important pros / cons to call out?
- What guidance do we want to give?

I _think_ I'm leaning towards having ContinuousIntegrationBuild automatically set by the SDK (ideally this part: https://github.com/dotnet/reproducible-builds/blob/7cf65de99f502a5238065a420b772ba737ab96f5/src/DotNet.ReproducibleBuilds/DotNet.ReproducibleBuilds.props#L15-L38) and then publishing guidance that it's the preferred way to do this sort of customization.

As always, I'm sure there's a lot that I'm missing, so thoughts, suggestions, and alternatives all welcome. Tagging @baronfel as someone who may be an owner here? Also tagging @jaredpar who I assume has opinions in this space, and @rainersigwald for FYI as well.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.