-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Support file-based apps in user-secrets #63496
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <root> | ||
| <!-- | ||
| Microsoft ResX Schema | ||
|
|
@@ -133,15 +133,9 @@ Use the '--help' flag to see info.</value> | |
| <data name="Error_No_Secrets_Found" xml:space="preserve"> | ||
| <value>No secrets configured for this application.</value> | ||
| </data> | ||
| <data name="Error_NoProjectsFound" xml:space="preserve"> | ||
| <value>Could not find a MSBuild project file in '{projectPath}'. Specify which project to use with the --project option.</value> | ||
| </data> | ||
| <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"> | ||
| <value>The project file '{path}' does not exist.</value> | ||
| </data> | ||
| <data name="Error_ProjectFailedToLoad" xml:space="preserve"> | ||
| <value>Could not load the MSBuild project '{project}'.</value> | ||
| </data> | ||
|
|
@@ -169,4 +163,10 @@ Use the '--help' flag to see info.</value> | |
| <data name="Message_SetUserSecretsIdForProject" xml:space="preserve"> | ||
| <value>Set UserSecretsId to '{userSecretsId}' for MSBuild project '{project}'.</value> | ||
| </data> | ||
| </root> | ||
| <data name="Error_ProjectAndFileOptions" xml:space="preserve"> | ||
| <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> | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. |
||
| </data> | ||
| </root> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ | |
| using System.IO; | ||
| using System.Text; | ||
| using Microsoft.AspNetCore.InternalTesting; | ||
| using Microsoft.AspNetCore.Tools; | ||
| using Microsoft.Extensions.Configuration.UserSecrets; | ||
| using Microsoft.Extensions.Configuration.UserSecrets.Tests; | ||
| using Microsoft.Extensions.Tools.Internal; | ||
|
|
@@ -64,7 +65,27 @@ public void Error_Project_DoesNotExist() | |
| var secretManager = CreateProgram(); | ||
|
|
||
| secretManager.RunInternal("list", "--project", projectPath); | ||
| Assert.Contains(Resources.FormatError_ProjectPath_NotFound(projectPath), _console.GetOutput()); | ||
| Assert.Contains(SecretsHelpersResources.FormatError_File_NotFound(projectPath), _console.GetOutput()); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Error_ProjectAndFileOptions() | ||
| { | ||
| var projectPath = Path.Combine(_fixture.GetTempSecretProject(), "does_not_exist", "TestProject.csproj"); | ||
| var secretManager = CreateProgram(); | ||
|
|
||
| secretManager.RunInternal("list", "--project", projectPath, "--file", projectPath); | ||
| Assert.Contains(Resources.Error_ProjectAndFileOptions, _console.GetOutput()); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Error_InitFile() | ||
| { | ||
| var dir = _fixture.CreateFileBasedApp(null); | ||
jjonescz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| var secretManager = CreateProgram(); | ||
|
|
||
| secretManager.RunInternal("init", "--file", Path.Combine(dir, "app.cs")); | ||
| Assert.Contains(Resources.Error_InitNotSupportedForFileBasedApps, _console.GetOutput()); | ||
| } | ||
|
|
||
| [Fact] | ||
|
|
@@ -81,9 +102,10 @@ public void SupportsRelativePaths() | |
| } | ||
|
|
||
| [Theory] | ||
| [InlineData(true)] | ||
| [InlineData(false)] | ||
| public void SetSecrets(bool fromCurrentDirectory) | ||
| [InlineData(false, true)] | ||
| [InlineData(false, false)] | ||
| [InlineData(true, false)] | ||
| public void SetSecrets(bool fromCurrentDirectory, bool fileBasedApp) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is currently valid, the test verifies that (
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
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
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will add a test for this, thanks. |
||
| { | ||
| var secrets = new KeyValuePair<string, string>[] | ||
| { | ||
|
|
@@ -95,18 +117,22 @@ public void SetSecrets(bool fromCurrentDirectory) | |
| new KeyValuePair<string, string>("--twoDashedKey", "--twoDashedValue") | ||
| }; | ||
|
|
||
| var projectPath = _fixture.GetTempSecretProject(); | ||
| var projectPath = fileBasedApp | ||
| ? _fixture.GetTempFileBasedApp(out _) | ||
| : _fixture.GetTempSecretProject(); | ||
| var dir = fromCurrentDirectory | ||
| ? projectPath | ||
| : Path.GetTempPath(); | ||
| ReadOnlySpan<string> pathArgs = fromCurrentDirectory | ||
| ? [] | ||
| : (fileBasedApp | ||
| ? ["-f", Path.Join(projectPath, "app.cs")] | ||
| : ["-p", projectPath]); | ||
| var secretManager = new Program(_console, dir); | ||
|
|
||
| foreach (var secret in secrets) | ||
| { | ||
| var parameters = fromCurrentDirectory ? | ||
| new string[] { "set", secret.Key, secret.Value, "--verbose" } : | ||
| new string[] { "set", secret.Key, secret.Value, "-p", projectPath, "--verbose" }; | ||
| secretManager.RunInternal(parameters); | ||
| secretManager.RunInternal(["set", secret.Key, secret.Value, .. pathArgs, "--verbose"]); | ||
| } | ||
|
|
||
| foreach (var keyValue in secrets) | ||
|
|
@@ -117,10 +143,7 @@ public void SetSecrets(bool fromCurrentDirectory) | |
| } | ||
|
|
||
| _console.ClearOutput(); | ||
| var args = fromCurrentDirectory | ||
| ? new string[] { "list", "--verbose" } | ||
| : new string[] { "list", "-p", projectPath, "--verbose" }; | ||
| secretManager.RunInternal(args); | ||
| secretManager.RunInternal(["list", .. pathArgs, "--verbose"]); | ||
| foreach (var keyValue in secrets) | ||
| { | ||
| Assert.Contains( | ||
|
|
@@ -132,21 +155,24 @@ public void SetSecrets(bool fromCurrentDirectory) | |
| _console.ClearOutput(); | ||
| foreach (var secret in secrets) | ||
| { | ||
| var parameters = fromCurrentDirectory ? | ||
| new string[] { "remove", secret.Key, "--verbose" } : | ||
| new string[] { "remove", secret.Key, "-p", projectPath, "--verbose" }; | ||
| secretManager.RunInternal(parameters); | ||
| secretManager.RunInternal(["remove", secret.Key, .. pathArgs, "--verbose"]); | ||
| } | ||
|
|
||
| // Verify secrets are removed. | ||
| _console.ClearOutput(); | ||
| args = fromCurrentDirectory | ||
| ? new string[] { "list", "--verbose" } | ||
| : new string[] { "list", "-p", projectPath, "--verbose" }; | ||
| secretManager.RunInternal(args); | ||
| secretManager.RunInternal(["list", .. pathArgs, "--verbose"]); | ||
| Assert.Contains(Resources.Error_No_Secrets_Found, _console.GetOutput()); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void SetSecrets_FileBasedAppInCurrentDirectory() | ||
| { | ||
| var directoryPath = _fixture.GetTempFileBasedApp(out _); | ||
| var secretManager = new Program(_console, directoryPath); | ||
| secretManager.RunInternal("set", "key1", "value1", "--verbose"); | ||
| Assert.Contains(SecretsHelpersResources.FormatError_NoProjectsFound(directoryPath), _console.GetOutput()); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void SetSecret_Update_Existing_Secret() | ||
| { | ||
|
|
@@ -268,16 +294,25 @@ public void List_Empty_Secrets_File() | |
| } | ||
|
|
||
| [Theory] | ||
| [InlineData(true)] | ||
| [InlineData(false)] | ||
| public void Clear_Secrets(bool fromCurrentDirectory) | ||
| [InlineData(false, true)] | ||
| [InlineData(false, false)] | ||
| [InlineData(true, false)] | ||
| public void Clear_Secrets(bool fromCurrentDirectory, bool fileBasedApp) | ||
| { | ||
| var projectPath = _fixture.GetTempSecretProject(); | ||
| var projectPath = fileBasedApp | ||
| ? _fixture.GetTempFileBasedApp(out _) | ||
| : _fixture.GetTempSecretProject(); | ||
|
|
||
| var dir = fromCurrentDirectory | ||
| ? projectPath | ||
| : Path.GetTempPath(); | ||
|
|
||
| ReadOnlySpan<string> pathArgs = fromCurrentDirectory | ||
| ? [] | ||
| : (fileBasedApp | ||
| ? ["-f", Path.Join(projectPath, "app.cs")] | ||
| : ["-p", projectPath]); | ||
|
|
||
| var secretManager = new Program(_console, dir); | ||
|
|
||
| var secrets = new KeyValuePair<string, string>[] | ||
|
|
@@ -290,10 +325,7 @@ public void Clear_Secrets(bool fromCurrentDirectory) | |
|
|
||
| foreach (var secret in secrets) | ||
| { | ||
| var parameters = fromCurrentDirectory ? | ||
| new string[] { "set", secret.Key, secret.Value, "--verbose" } : | ||
| new string[] { "set", secret.Key, secret.Value, "-p", projectPath, "--verbose" }; | ||
| secretManager.RunInternal(parameters); | ||
| secretManager.RunInternal(["set", secret.Key, secret.Value, .. pathArgs, "--verbose"]); | ||
| } | ||
|
|
||
| foreach (var keyValue in secrets) | ||
|
|
@@ -305,10 +337,7 @@ public void Clear_Secrets(bool fromCurrentDirectory) | |
|
|
||
| // Verify secrets are persisted. | ||
| _console.ClearOutput(); | ||
| var args = fromCurrentDirectory ? | ||
| new string[] { "list", "--verbose" } : | ||
| new string[] { "list", "-p", projectPath, "--verbose" }; | ||
| secretManager.RunInternal(args); | ||
| secretManager.RunInternal(["list", .. pathArgs, "--verbose"]); | ||
| foreach (var keyValue in secrets) | ||
| { | ||
| Assert.Contains( | ||
|
|
@@ -318,11 +347,9 @@ public void Clear_Secrets(bool fromCurrentDirectory) | |
|
|
||
| // Clear secrets. | ||
| _console.ClearOutput(); | ||
| args = fromCurrentDirectory ? new string[] { "clear", "--verbose" } : new string[] { "clear", "-p", projectPath, "--verbose" }; | ||
| secretManager.RunInternal(args); | ||
| secretManager.RunInternal(["clear", .. pathArgs, "--verbose"]); | ||
|
|
||
| args = fromCurrentDirectory ? new string[] { "list", "--verbose" } : new string[] { "list", "-p", projectPath, "--verbose" }; | ||
| secretManager.RunInternal(args); | ||
| secretManager.RunInternal(["list", .. pathArgs, "--verbose"]); | ||
| Assert.Contains(Resources.Error_No_Secrets_Found, _console.GetOutput()); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
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
msbuildtobuildfor this? Also, I assume this exists because there are file-based app behaviors that are not available inmsbuild?There was a problem hiding this comment.
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.