Skip to content

Conversation

@jjonescz
Copy link
Member

@jjonescz jjonescz commented Sep 1, 2025

Support file-based apps in user-secrets

Makes the dotnet user-secrets tool work for file-based apps (via a new --file argument) analogously to how it works for project-based apps today.

Description

Supports dotnet user-secrets commands for file-based apps except dotnet user-secrets init (currently you have to set #:property UserSecretsId=... manually but we plan to add support for implicit UserSecretsIds in file-based apps but the technical side of that is still being discussed).

Resolves #63440.

Customer Impact

Driven by Aspire needs.

Regression?

  • Yes
  • No - this is a new feature

Risk

  • High
  • Medium
  • Low - this is a new feature which shouldn't affect any existing features

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

@jjonescz jjonescz marked this pull request as ready for review September 2, 2025 18:02
Copilot AI review requested due to automatic review settings September 2, 2025 18:02
@jjonescz
Copy link
Member Author

jjonescz commented Sep 2, 2025

cc @dotnet/run-file

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds support for file-based apps in the dotnet-user-secrets tool, addressing issue #63440. The changes enable the tool to work with file-based C# apps that use #:property UserSecretsId=... directives instead of traditional MSBuild project files.

Key changes include:

  • Added --file option to specify file-based apps alongside the existing --project option
  • Enhanced test infrastructure to support both project-based and file-based app testing
  • Updated error messages and resource strings to accommodate the new functionality

Reviewed Changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Tools/dotnet-user-secrets/test/UserSecretsTestFixture.cs Added test helper methods for creating and managing file-based app test scenarios
src/Tools/dotnet-user-secrets/test/SecretManagerTests.cs Enhanced existing tests to cover file-based apps and added validation for new error conditions
src/Tools/dotnet-user-secrets/src/Resources.resx Added new error messages for file-based app scenarios and removed unused resource entries
src/Tools/dotnet-user-secrets/src/Program.cs Updated ID resolution logic to handle both project and file options
src/Tools/dotnet-user-secrets/src/Internal/InitCommand.cs Added validation to prevent init command usage with file-based apps
src/Tools/dotnet-user-secrets/src/CommandLineOptions.cs Added --file option parsing and mutual exclusion validation with --project
src/Tools/Shared/SecretsHelpers/SecretsHelpersResources.resx Updated error messages to mention the new --file option for better user guidance
src/Tools/Shared/SecretsHelpers/ProjectIdResolver.cs Changed MSBuild command from msbuild to build with updated arguments

@jjonescz
Copy link
Member Author

jjonescz commented Sep 3, 2025

@DamianEdwards any idea who I need reviews from here?

ArgumentList =
{
"msbuild",
"build",
Copy link
Member

Choose a reason for hiding this comment

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

Are there any gotchas we should be on the lookout for as we move from msbuild to build for this? Also, I assume this exists because there are file-based app behaviors that are not available in msbuild?

Copy link
Member

Choose a reason for hiding this comment

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

msbuild is the 'raw' interface. it doesn't do multi-processing by default, doesn't do terminal logger (though you're not going to see that one), it doesn't do implicit restores, etc. build will do all of those (and it has the nice CLI args for some of the common properties) in addition to supporting the file-based apps. I'd say in general you should expect more churn in the behavior of build, but we do try to keep the contract pretty clean and consistent.

[InlineData(false, true)]
[InlineData(false, false)]
[InlineData(true, false)]
public void SetSecrets(bool fromCurrentDirectory, bool fileBasedApp)
Copy link
Member

Choose a reason for hiding this comment

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

Should we error if you try to set secrets on a file-based app from a directory that the file is not in? Based on the options here, it seems like calling the below would be invalid?

$ pwd
/user/some/dir
$ dotnet user-secrets set "foo" "bar" --file /user/some/otherdir/file.cs

Copy link
Member Author

@jjonescz jjonescz Sep 4, 2025

Choose a reason for hiding this comment

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

That is currently valid, the test verifies that (fromCurrentDirectory: false, fileBasedApp: true). What's invalid is when no --project and no --file is specified - that works if you are in the project's directory, but not for file-based apps (there could be multiple file-based apps in the directory).

Copy link
Member

Choose a reason for hiding this comment

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

What's invalid is when no --project and no --file is specified - that works if you are in the project's directory, but not for file-based apps (there could be multiple file-based apps in the directory).

Is there test coverage for this case? No project file in the current directory, but there are file-based app(s) in the current directory, and no --project and no --file arg is passed?

Copy link
Member Author

Choose a reason for hiding this comment

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

I will add a test for this, thanks.

@RikkiGibson RikkiGibson self-assigned this Sep 4, 2025
Copy link
Member

@RikkiGibson RikkiGibson left a comment

Choose a reason for hiding this comment

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

LGTM with some questions/nits

<data name="Error_ProjectMissingId" xml:space="preserve">
<value>Could not find the global property 'UserSecretsId' in MSBuild project '{project}'. Ensure this property is set in the project or use the '--id' command line option.</value>
</data>
<data name="Error_ProjectPath_NotFound" xml:space="preserve">
Copy link
Member

Choose a reason for hiding this comment

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

Should resource name also be changed?

<value>Cannot use both --file and --project options together.</value>
</data>
<data name="Error_InitNotSupportedForFileBasedApps" xml:space="preserve">
<value>Init command is currently not supported for file-based apps. Please add '#:property UserSecretsId=...' manually.</value>
Copy link
Member

Choose a reason for hiding this comment

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

All this command does is generate a guid and stick it in the UserSecretsId in the user's project? Is that right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes.

var parameters = fromCurrentDirectory ?
new string[] { "set", secret.Key, secret.Value, "--verbose" } :
new string[] { "set", secret.Key, secret.Value, "-p", projectPath, "--verbose" };
[ "set", secret.Key, secret.Value, .. pathArgs, "--verbose" ];
Copy link
Member

Choose a reason for hiding this comment

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

nit: wonder if it would be simplifying if pathArgs was always included, and in the case fromCurrentDirectory is true, we would just ensure pathArgs is empty.

[InlineData(false, true)]
[InlineData(false, false)]
[InlineData(true, false)]
public void SetSecrets(bool fromCurrentDirectory, bool fileBasedApp)
Copy link
Member

Choose a reason for hiding this comment

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

What's invalid is when no --project and no --file is specified - that works if you are in the project's directory, but not for file-based apps (there could be multiple file-based apps in the directory).

Is there test coverage for this case? No project file in the current directory, but there are file-based app(s) in the current directory, and no --project and no --file arg is passed?

@danmoseley
Copy link
Member

@captainsafia is this intentionally against the RC2 branch? I assume we'll have a template in due course?

@jjonescz
Copy link
Member Author

jjonescz commented Sep 8, 2025

is this intentionally against the RC2 branch? I assume we'll have a template in due course?

This is intentionally targeting .NET 10, yes. I'm not sure what template you have in mind with relation to this PR.

@captainsafia
Copy link
Member

is this intentionally against the RC2 branch? I assume we'll have a template in due course?

This is intentionally targeting .NET 10, yes. I'm not sure what template you have in mind with relation to this PR.

@danmoseley is referring to the template here: https://github.com/dotnet/aspnetcore/blob/main/.github/PULL_REQUEST_TEMPLATE/servicing.md. You can see it in action in this PR.

@baronfel
Copy link
Member

baronfel commented Sep 8, 2025

It's a little wonky because SDK and most other 'tooling' is open through RC2 generally, but since this change is shared with a more 'runtime'-behaving component the process is a little off by comparison.

@jjonescz
Copy link
Member Author

jjonescz commented Sep 9, 2025

I've filled the template in the PR's description.

@jjonescz
Copy link
Member Author

@captainsafia do I need something else to get this merged? Thanks

@jjonescz
Copy link
Member Author

I have a follow-up PR here ready as well (to implicitly compute UserSecretsId if it's not set in the project/file-based app), so would like to get this merged soon.

@captainsafia captainsafia added area-commandlinetools Includes: Command line tools, dotnet-dev-certs, dotnet-user-jwts, and OpenAPI Servicing-consider Shiproom approval is required for the issue labels Sep 11, 2025
@danmoseley danmoseley added Servicing-approved Shiproom has approved the issue and removed Servicing-consider Shiproom approval is required for the issue labels Sep 11, 2025
@captainsafia
Copy link
Member

@dotnet/aspnet-build Can we get help merging this? There's a follow-up PR that needs to be taken through as well.

@DamianEdwards
Copy link
Member

There's a follow-up PR that needs to be taken through as well.

@captainsafia I think we don't need the follow-up PR anymore as the required change is going directly into dotnet/sdk now, but this PR, definitely 😄

@wtgodbe wtgodbe merged commit f7d34bf into dotnet:release/10.0 Sep 16, 2025
28 checks passed
@dotnet-policy-service dotnet-policy-service bot added this to the 10.0-rc2 milestone Sep 16, 2025
@jjonescz jjonescz deleted the sprint-user-secrets branch September 17, 2025 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-commandlinetools Includes: Command line tools, dotnet-dev-certs, dotnet-user-jwts, and OpenAPI Servicing-approved Shiproom has approved the issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants