Skip to content

Re-enable support for deterministic pack#7020

Open
omajid wants to merge 1 commit intoNuGet:devfrom
omajid:deterministic-pack-nuspec-file
Open

Re-enable support for deterministic pack#7020
omajid wants to merge 1 commit intoNuGet:devfrom
omajid:deterministic-pack-nuspec-file

Conversation

@omajid
Copy link
Copy Markdown
Contributor

@omajid omajid commented Dec 29, 2025

Bug

Fixes: NuGet/Home#8601

Description

Re-enable support for deterministic pack

Make NuGet pack more determinisitic, by default.

This makes Deterministic property (default = true) work again for nuget pack via msbuild.

It adds support for DeterministicTimestamp property (default = true) too.

For more details about the properties and the design goals, see:

PR Checklist

  • Meaningful title, helpful description and a linked NuGet/Home issue
  • Added tests
  • Link to an issue or pull request to update docs if this PR changes settings, environment variables, new feature, etc.

@dotnet-policy-service dotnet-policy-service bot added the Community PRs created by someone not in the NuGet team label Dec 29, 2025
@omajid omajid force-pushed the deterministic-pack-nuspec-file branch 5 times, most recently from aa6ce30 to 50b60af Compare December 29, 2025 23:25
@dotnet-policy-service dotnet-policy-service bot added the Status:No recent activity PRs that have not had any recent activity and will be closed if the label is not removed label Jan 6, 2026
@omajid omajid force-pushed the deterministic-pack-nuspec-file branch from 50b60af to 1ca6cc7 Compare January 31, 2026 13:51
@dotnet-policy-service dotnet-policy-service bot removed the Status:No recent activity PRs that have not had any recent activity and will be closed if the label is not removed label Jan 31, 2026
@omajid omajid force-pushed the deterministic-pack-nuspec-file branch 3 times, most recently from 00711c7 to 57cd90d Compare February 9, 2026 14:31
@dotnet-policy-service dotnet-policy-service bot added the Status:No recent activity PRs that have not had any recent activity and will be closed if the label is not removed label Feb 16, 2026
@omajid omajid force-pushed the deterministic-pack-nuspec-file branch from 57cd90d to eda2ff0 Compare February 24, 2026 15:50
@dotnet-policy-service dotnet-policy-service bot removed the Status:No recent activity PRs that have not had any recent activity and will be closed if the label is not removed label Feb 24, 2026
@omajid omajid force-pushed the deterministic-pack-nuspec-file branch 7 times, most recently from e1e6e37 to 8e626f9 Compare February 27, 2026 12:04
@omajid omajid marked this pull request as ready for review February 27, 2026 12:05
@omajid omajid requested a review from a team as a code owner February 27, 2026 12:05
PackageLicenseExpressionVersion="$(PackageLicenseExpressionVersion)"
Readme="$(PackageReadmeFile)"
Deterministic="$(Deterministic)"
DeterministicTimestamp="$(DeterministicTimestamp)"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I add a test for the task with deterministic timestamp?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like there are already two skipped tests that should be re-enabled: https://github.com/search?q=repo%3ANuGet%2FNuGet.Client+Deterministic+path%3Atest%2F**&type=code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, already enabled.

I was thinking more of a test involving the msbuild task (without running the pack command directly) somehow.

}

private PackageBuilder(bool includeEmptyDirectories, bool deterministic)
: this(includeEmptyDirectories: false, deterministic: deterministic, logger: NullLogger.Instance)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this includeEmptyDirectories: false a bug?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

certainly looks like it

{
}

public PackageBuilder(string path, Func<string, string> propertyProvider, bool includeEmptyDirectories, bool deterministic, string deterministicTimestamp, ILogger logger, string versionOverride)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class is approaching 20 constructors and is quite hard to parse, specially in terms of how constructors invoke each other (via : this(...)) Any tips on what to do here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you use a get; init; property for anything new? It only works if the "main" constructor doesn't do any real business logic. You'll need to make sure the new properties are not required and are either nullable or have default values that do not cause API or ABI breaking changes. But this is my favorite technique for avoiding constructor overload explosion.

private static DateTimeOffset ParseTimestamp(string timestamp)
{
if (timestamp != null &&
long.TryParse(timestamp, NumberStyles.None, CultureInfo.InvariantCulture, out long unixTimeSeconds))
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This lets us do something like DeterministicTimestamp = $(SOURCE_BUILD_EPOCH) and have that work.

Alternatively, should I add explicit support for SOURCE_BUILD_EPOCH directly?

See NuGet/Home#8601 (comment)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

@akoeplinger akoeplinger Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my preference would be if setting the SOURCE_DATE_EPOCH env var would just work without the user needing to pass it explicitly to the build

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be my preference too. Let me do that.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think env vars should only be used as an absolute last resort.
They are the worst UX because they're effectively a thing that keeps getting perpetuated because it's easy.

This all to say, I get that there's some sort of consensus on that env var, but if that were to be used, I think it should just be used as a default rather than something the nuget code reads internally (so have it initialize an msbuild property).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so have it initialize an msbuild property.

+1

</package>");

var command = "pack packageA.nuspec -Deterministic -OutputDirectory {0}";
var timestamp = DateTimeOffset.UtcNow;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I hardocde a fixed time to make test runs easier to compare?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

Copy link
Copy Markdown
Member

@nkolev92 nkolev92 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing the work here @omajid, we really appreciate it.

The comment in the PR I left tells me we are still effectively designing how the feature should work, and the PR description itself doesn't really carry details about what's been agreed upon in the long thread.

I think we should have some sort of a design here. This should both aid the reviewer here, as well as the documentation later on, on how determine pack can and should be used.

private static DateTimeOffset ParseTimestamp(string timestamp)
{
if (timestamp != null &&
long.TryParse(timestamp, NumberStyles.None, CultureInfo.InvariantCulture, out long unixTimeSeconds))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think env vars should only be used as an absolute last resort.
They are the worst UX because they're effectively a thing that keeps getting perpetuated because it's easy.

This all to say, I get that there's some sort of consensus on that env var, but if that were to be used, I think it should just be used as a default rather than something the nuget code reads internally (so have it initialize an msbuild property).

@omajid
Copy link
Copy Markdown
Contributor Author

omajid commented Mar 2, 2026

I think we should have some sort of a design here.

Can you point me to an example design? I am trying to understand the amount of detail and the actual format needed for the design. Thanks!

@nkolev92
Copy link
Copy Markdown
Member

nkolev92 commented Mar 2, 2026

@omajid

Template: https://github.com/NuGet/Home/blob/dev/meta/template.md.

The amount of detail is dependent on the complexity of the change.
In your case, I wouldn't expect much detail in the technical explanation part, since that is straightforward.
It's all about the functional side, what needs set, the precedence, defaults etc.

https://github.com/NuGet/Home/tree/dev/accepted/2025 has a bunch of specs:
Some of the shorter ones:

@omajid
Copy link
Copy Markdown
Contributor Author

omajid commented Mar 3, 2026

Design doc at NuGet/Home#14785

@omajid omajid force-pushed the deterministic-pack-nuspec-file branch from 8e626f9 to 0433cdc Compare March 10, 2026 17:31
@dotnet-policy-service dotnet-policy-service bot added the Status:No recent activity PRs that have not had any recent activity and will be closed if the label is not removed label Mar 17, 2026
@omajid
Copy link
Copy Markdown
Contributor Author

omajid commented Mar 18, 2026

I am waiting for the design doc to be approved before updating this PR.

@dotnet-policy-service dotnet-policy-service bot removed the Status:No recent activity PRs that have not had any recent activity and will be closed if the label is not removed label Mar 18, 2026
@dotnet-policy-service dotnet-policy-service bot added the Status:No recent activity PRs that have not had any recent activity and will be closed if the label is not removed label Mar 25, 2026
@Frulfump
Copy link
Copy Markdown

This PR has been automatically marked as stale because it has no activity for 7 days. It will be closed if no further activity occurs within another 30 days of this comment. If it is closed, you may reopen it anytime when you're ready again, as long as you don't delete the branch.

This bot is so annoying, is there no tag that could be added to get it to go away? A large portion of my GitHub notifications is from this bot or similar.

@dotnet-policy-service dotnet-policy-service bot removed the Status:No recent activity PRs that have not had any recent activity and will be closed if the label is not removed label Mar 25, 2026
@omajid omajid force-pushed the deterministic-pack-nuspec-file branch 2 times, most recently from 6e87959 to 4b52b5d Compare March 26, 2026 22:06
@akoeplinger
Copy link
Copy Markdown
Contributor

akoeplinger commented Mar 27, 2026

/azp run (retriggering due to the Azure Pipelines outage yesterday)

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@azure-pipelines
Copy link
Copy Markdown

No pipelines are associated with this pull request.

Make NuGet pack more determinisitic, by default.

This makes `Deterministic` property (default = `true`) work again for
nuget pack via msbuild.

It adds support for `DeterministicTimestamp` property (default = `true`)
too.

For more details about the properties and the design goals, see:

- NuGet/Home#14785
- https://github.com/NuGet/Home/main/accepted/2026/deterministic-pack-revisited.md

Fixes: NuGet/Home#8601
@omajid omajid force-pushed the deterministic-pack-nuspec-file branch from 4b52b5d to 1f979fb Compare March 27, 2026 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Community PRs created by someone not in the NuGet team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Revisit deterministic pack

5 participants