Skip to content

Commit b6a45aa

Browse files
authored
[backport 9.4] aspire exec fixes (#10628)
* chore: `aspire exec --help` improvements (#10598) * provide more info in help * rsc changes * typo * include COMMAND LINE to be explicit * with examples * fix: `aspire exec` fail fast improvements (#10606) * fix aot (#10625) * fix build
1 parent 4ed44ce commit b6a45aa

19 files changed

+585
-200
lines changed

src/Aspire.Cli/Commands/ExecCommand.cs

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ public ExecCommand(
6767
startResourceOption.Description = ExecCommandStrings.StartTargetResourceArgumentDescription;
6868
Options.Add(startResourceOption);
6969

70+
// only for --help output
71+
var commandOption = new Option<string>("--");
72+
commandOption.Description = ExecCommandStrings.CommandArgumentDescription;
73+
Options.Add(commandOption);
74+
7075
TreatUnmatchedTokensAsErrors = false;
7176
}
7277

@@ -78,6 +83,37 @@ protected override async Task<int> ExecuteAsync(ParseResult parseResult, Cancell
7883
return ExitCodeConstants.SdkNotInstalled;
7984
}
8085

86+
// validate required arguments firstly to fail fast if not found
87+
var targetResourceMode = "--resource";
88+
var targetResource = parseResult.GetValue<string>("--resource");
89+
if (string.IsNullOrEmpty(targetResource))
90+
{
91+
targetResourceMode = "--start-resource";
92+
targetResource = parseResult.GetValue<string>("--start-resource");
93+
}
94+
95+
if (targetResource is null)
96+
{
97+
_interactionService.DisplayError(ExecCommandStrings.TargetResourceNotSpecified);
98+
return ExitCodeConstants.InvalidCommand;
99+
}
100+
101+
// unmatched tokens are those which will be tried to parse as command.
102+
// if none - we should fail fast
103+
if (parseResult.UnmatchedTokens.Count == 0)
104+
{
105+
_interactionService.DisplayError(ExecCommandStrings.NoCommandSpecified);
106+
return ExitCodeConstants.InvalidCommand;
107+
}
108+
109+
var (arbitraryFlags, commandTokens) = ParseCmdArgs(parseResult);
110+
111+
if (commandTokens is null || commandTokens.Count == 0)
112+
{
113+
_interactionService.DisplayError(ExecCommandStrings.FailedToParseCommand);
114+
return ExitCodeConstants.InvalidCommand;
115+
}
116+
81117
var buildOutputCollector = new OutputCollector();
82118
var runOutputCollector = new OutputCollector();
83119

@@ -118,28 +154,6 @@ protected override async Task<int> ExecuteAsync(ParseResult parseResult, Cancell
118154
StandardErrorCallback = runOutputCollector.AppendError,
119155
};
120156

121-
var targetResourceMode = "--resource";
122-
var targetResource = parseResult.GetValue<string>("--resource");
123-
if (string.IsNullOrEmpty(targetResource))
124-
{
125-
targetResourceMode = "--start-resource";
126-
targetResource = parseResult.GetValue<string>("--start-resource");
127-
}
128-
129-
if (targetResource is null)
130-
{
131-
_interactionService.DisplayError(ExecCommandStrings.TargetResourceNotSpecified);
132-
return ExitCodeConstants.InvalidCommand;
133-
}
134-
135-
var (arbitraryFlags, commandTokens) = ParseCmdArgs(parseResult);
136-
137-
if (commandTokens is null || commandTokens.Count == 0)
138-
{
139-
_interactionService.DisplayError(ExecCommandStrings.FailedToParseCommand);
140-
return ExitCodeConstants.InvalidCommand;
141-
}
142-
143157
string[] args = [
144158
"--operation", "run",
145159
targetResourceMode, targetResource!,

src/Aspire.Cli/Resources/ExecCommandStrings.Designer.cs

Lines changed: 30 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Aspire.Cli/Resources/ExecCommandStrings.resx

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,21 +118,33 @@
118118
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
119119
</resheader>
120120
<data name="Description" xml:space="preserve">
121-
<value>Run an Aspire app host to execute a command against the resource. (Preview)</value>
121+
<value>Execute commands in the context of an Aspire application resource. Starts the AppHost, waits for resources to initialize, then runs the specified command in the target resource's environment. (Preview)
122+
123+
Examples:
124+
aspire exec --resource api dotnet build
125+
aspire exec --resource api -- dotnet test --logger console
126+
aspire exec --start-resource worker pwsh -c "Get-Process"
127+
</value>
122128
</data>
123129
<data name="ProjectArgumentDescription" xml:space="preserve">
124-
<value>The path to the Aspire app host project file.</value>
130+
<value>The path to the Aspire AppHost project file. If not specified, searches for a project file in the current directory.</value>
125131
</data>
126132
<data name="StartTargetResourceArgumentDescription" xml:space="preserve">
127-
<value>The name of the target resource to start and execute the command against.</value>
133+
<value>The name of the target resource to execute the command against. The command will only be executed after the target resource has successfully started and is running.</value>
128134
</data>
129135
<data name="TargetResourceArgumentDescription" xml:space="preserve">
130-
<value>The name of the target resource to execute the command against.</value>
136+
<value>The name of the target resource to execute the command against. The command will be executed as soon as the AppHost starts, without waiting for the resource to be ready.</value>
131137
</data>
132138
<data name="TargetResourceNotSpecified" xml:space="preserve">
133-
<value>Target resource is not specified.</value>
139+
<value>Target resource is not specified. Use --resource or --start-resource to specify the target.</value>
134140
</data>
135141
<data name="FailedToParseCommand" xml:space="preserve">
136-
<value>Failed to parse command.</value>
142+
<value>Failed to parse the command. Ensure the command is specified after all options or after the -- separator.</value>
143+
</data>
144+
<data name="CommandArgumentDescription" xml:space="preserve">
145+
<value>The command to execute in the target resource's context. Commands can be specified directly after options or after a -- separator.</value>
146+
</data>
147+
<data name="NoCommandSpecified" xml:space="preserve">
148+
<value>Command is not specified.</value>
137149
</data>
138-
</root>
150+
</root>

src/Aspire.Cli/Resources/xlf/ExecCommandStrings.cs.xlf

Lines changed: 34 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Aspire.Cli/Resources/xlf/ExecCommandStrings.de.xlf

Lines changed: 34 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)