Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions docs/specs/with-terminal.md
Original file line number Diff line number Diff line change
Expand Up @@ -518,15 +518,14 @@ backchannel response has required `resourceTerminals` and `appHostTerminals`
arrays, each empty when there are no terminals of that kind. Resource entries
group their replicas; AppHost entries carry a terminal ID, title, and placement.
The CLI's `--format json` output combines both into one array with an `owner`
discriminator. Terminal commands are gated by `features.terminalCommandsEnabled`;
discriminator. Terminal commands are available without a feature flag;
their experimental backchannel contract can change between builds.

### Tape playback

`aspire terminal tape play <resource> --tape-file <path>` uses Hex1b's
`TapeParser` and `TapePlayer` to execute a VHS `.tape` script against an
existing resource terminal. It requires the same `features.terminalCommandsEnabled` feature
flag as `terminal attach` and `terminal ps`.
existing resource terminal.

```sh
aspire terminal tape play shell --tape-file ./probe.tape
Expand Down
16 changes: 0 additions & 16 deletions extension/schemas/aspire-config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -221,22 +221,6 @@
"description": "Enable or disable access to the staging channel for early access to preview features and packages",
"default": false
},
"terminalCommandsEnabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "string",
"enum": [
"true",
"false"
]
}
],
"description": "(Experimental) Enable the 'aspire terminal' command group ('aspire terminal ps', 'aspire terminal attach'). Used in conjunction with the experimental WithTerminal() API (ASPIRETERMINAL001). Hidden by default while the API surface is in preview.",
"default": false
},
"updateNotificationsEnabled": {
"anyOf": [
{
Expand Down
16 changes: 0 additions & 16 deletions extension/schemas/aspire-global-settings.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,22 +173,6 @@
"description": "Enable or disable access to the staging channel for early access to preview features and packages",
"default": false
},
"terminalCommandsEnabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "string",
"enum": [
"true",
"false"
]
}
],
"description": "(Experimental) Enable the 'aspire terminal' command group ('aspire terminal ps', 'aspire terminal attach'). Used in conjunction with the experimental WithTerminal() API (ASPIRETERMINAL001). Hidden by default while the API surface is in preview.",
"default": false
},
"updateNotificationsEnabled": {
"anyOf": [
{
Expand Down
16 changes: 0 additions & 16 deletions extension/schemas/aspire-settings.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,22 +173,6 @@
"description": "Enable or disable access to the staging channel for early access to preview features and packages",
"default": false
},
"terminalCommandsEnabled": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "string",
"enum": [
"true",
"false"
]
}
],
"description": "(Experimental) Enable the 'aspire terminal' command group ('aspire terminal ps', 'aspire terminal attach'). Used in conjunction with the experimental WithTerminal() API (ASPIRETERMINAL001). Hidden by default while the API surface is in preview.",
"default": false
},
"updateNotificationsEnabled": {
"anyOf": [
{
Expand Down
9 changes: 1 addition & 8 deletions src/Aspire.Cli/Commands/RootCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

using Aspire.Cli.Bundles;
using Aspire.Cli.Commands.Sdk;
using Aspire.Cli.Configuration;
using Aspire.Cli.Interaction;
using Aspire.Cli.Resources;
using Aspire.Cli.Utils;
Expand Down Expand Up @@ -176,7 +175,6 @@ public RootCommand(
ExtensionInternalCommand extensionInternalCommand,
IBundleService bundleService,
IInteractionService interactionService,
IFeatures features,
IAnsiConsole ansiConsole,
CliExecutionContext executionContext)
: base(RootCommandStrings.Description)
Expand Down Expand Up @@ -228,12 +226,7 @@ public RootCommand(
Subcommands.Add(describeCommand);
Subcommands.Add(logsCommand);
Subcommands.Add(integrationCommand);
// 'aspire terminal' is hidden behind a feature flag while WithTerminal() is experimental.
// Toggle with `aspire config set features.terminalCommandsEnabled true`.
if (features.IsFeatureEnabled(KnownFeatures.TerminalCommandsEnabled, defaultValue: false))
{
Subcommands.Add(terminalCommand);
}
Subcommands.Add(terminalCommand);
Subcommands.Add(addCommand);
Subcommands.Add(publishCommand);
Subcommands.Add(configCommand);
Expand Down
6 changes: 0 additions & 6 deletions src/Aspire.Cli/KnownFeatures.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ internal static class KnownFeatures
public static string ExperimentalPolyglotPython => "experimentalPolyglot:python";
public static string NuGetSignatureVerificationEnabled => "nugetSignatureVerificationEnabled";
public static string AspireSkillsRemoteFetchEnabled => "aspireSkillsRemoteFetchEnabled";
public static string TerminalCommandsEnabled => "terminalCommandsEnabled";
public static string PolyglotIntegrationFilterEnabled => "polyglotIntegrationFilterEnabled";

private static readonly Dictionary<string, FeatureMetadata> s_featureMetadata = new()
Expand Down Expand Up @@ -99,11 +98,6 @@ internal static class KnownFeatures
// still honored if set directly in config.
Hidden: true),

[TerminalCommandsEnabled] = new(
TerminalCommandsEnabled,
"(Experimental) Enable the 'aspire terminal' command group ('aspire terminal ps', 'aspire terminal attach', 'aspire terminal tape play'). Used in conjunction with the experimental WithTerminal() API (ASPIRETERMINAL001). Hidden by default while the API surface is in preview.",
DefaultValue: false),

[PolyglotIntegrationFilterEnabled] = new(
PolyglotIntegrationFilterEnabled,
"(Experimental) Restrict 'aspire add', 'aspire integration list', and 'aspire integration search' in non-C# AppHosts to integrations carrying the 'polyglot' NuGet tag. Disabled by default because no remote feed resolves the tag usefully today: Azure DevOps Artifacts feeds ignore 'tags:' query scoping, and nuget.org returns no first-party integrations for it. The filter fails closed, so enabling it against a remote feed hides every integration. Enable it only against a local package source or hive, where the tag is read from the nuspec.",
Expand Down
1 change: 0 additions & 1 deletion tests/Aspire.Cli.EndToEnd.Tests/TerminalCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ public async Task TerminalAttachFrontend_ShowsViteHelpAndDetaches()
await auto.PrepareDockerEnvironmentAsync(counter, workspace);
await auto.InstallAspireCliAsync(strategy, counter);

await auto.RunCommandAsync("aspire config set features.terminalCommandsEnabled true -g", counter);
await auto.AspireNewAsync("TerminalSupportApp", counter, template: AspireTemplate.ExpressReact);

var appHostPath = Path.Combine(workspace.WorkspaceRoot.FullName, "TerminalSupportApp", "apphost.mts");
Expand Down
10 changes: 5 additions & 5 deletions tests/Aspire.Cli.Tests/Commands/TerminalCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class TerminalCommandTests(ITestOutputHelper outputHelper)
public async Task TerminalCommand_Help_Works()
{
using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, o => o.EnabledFeatures = [KnownFeatures.TerminalCommandsEnabled]);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper);
using var provider = services.BuildServiceProvider();

var command = provider.GetRequiredService<RootCommand>();
Expand All @@ -34,7 +34,7 @@ public async Task TerminalCommand_WhenNoSubcommand_PrintsHelpAndFails()
// The 'terminal' parent command is non-runnable; it prints help when invoked
// alone and returns InvalidCommand to mirror the DashboardCommand pattern.
using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, o => o.EnabledFeatures = [KnownFeatures.TerminalCommandsEnabled]);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper);
using var provider = services.BuildServiceProvider();

var command = provider.GetRequiredService<RootCommand>();
Expand All @@ -48,7 +48,7 @@ public async Task TerminalCommand_WhenNoSubcommand_PrintsHelpAndFails()
public async Task TerminalAttachCommand_WhenNoResourceArgument_FailsParsing()
{
using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, o => o.EnabledFeatures = [KnownFeatures.TerminalCommandsEnabled]);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper);
using var provider = services.BuildServiceProvider();

var command = provider.GetRequiredService<RootCommand>();
Expand All @@ -62,7 +62,7 @@ public async Task TerminalAttachCommand_WhenNoResourceArgument_FailsParsing()
public async Task TerminalCommand_WhenNoAppHostRunning_ReturnsSuccess()
{
using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, o => o.EnabledFeatures = [KnownFeatures.TerminalCommandsEnabled]);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper);
using var provider = services.BuildServiceProvider();

var command = provider.GetRequiredService<RootCommand>();
Expand Down Expand Up @@ -295,7 +295,7 @@ public async Task TerminalCommand_NonInteractiveMultiReplicaWithoutFlag_ReturnsI
public async Task TerminalPsCommand_WhenNoAppHostRunning_ReturnsSuccess()
{
using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, o => o.EnabledFeatures = [KnownFeatures.TerminalCommandsEnabled]);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper);
using var provider = services.BuildServiceProvider();

var command = provider.GetRequiredService<RootCommand>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class TerminalCommandViewerOptionTests(ITestOutputHelper outputHelper)
public void ViewerOption_Help_DescribesPrimarySecondaryBehaviour()
{
using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, o => o.EnabledFeatures = [KnownFeatures.TerminalCommandsEnabled]);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper);
using var provider = services.BuildServiceProvider();

var command = provider.GetRequiredService<RootCommand>();
Expand Down Expand Up @@ -47,7 +47,7 @@ public void ViewerOption_Help_DescribesPrimarySecondaryBehaviour()
public void ViewerOption_DefaultIsFalse_WhenNotSpecified()
{
using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, o => o.EnabledFeatures = [KnownFeatures.TerminalCommandsEnabled]);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper);
using var provider = services.BuildServiceProvider();

var command = provider.GetRequiredService<RootCommand>();
Expand All @@ -62,7 +62,7 @@ public void ViewerOption_DefaultIsFalse_WhenNotSpecified()
public void ViewerOption_ParsesToTrue_WhenSpecified()
{
using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, o => o.EnabledFeatures = [KnownFeatures.TerminalCommandsEnabled]);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper);
using var provider = services.BuildServiceProvider();

var command = provider.GetRequiredService<RootCommand>();
Expand Down
10 changes: 4 additions & 6 deletions tests/Aspire.Cli.Tests/Commands/TerminalTapePlayCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ public class TerminalTapePlayCommandTests(ITestOutputHelper outputHelper)
public async Task CommandHierarchy(string arguments, int expectedExitCode)
{
using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper,
options => options.EnabledFeatures = [KnownFeatures.TerminalCommandsEnabled]);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper);
using var provider = services.BuildServiceProvider();

var result = provider.GetRequiredService<RootCommand>().Parse(arguments);
Expand All @@ -33,15 +32,15 @@ public async Task CommandHierarchy(string arguments, int expectedExitCode)
}

[Fact]
public void RequiresTerminalFeature()
public void AvailableWithoutFeatureFlag()
{
using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper);
using var provider = services.BuildServiceProvider();

var result = provider.GetRequiredService<RootCommand>().Parse("terminal tape play shell --tape-file probe.tape");

Assert.NotEmpty(result.Errors);
Assert.Empty(result.Errors);
}

[Theory]
Expand Down Expand Up @@ -96,8 +95,7 @@ public async Task NoRunningAppHostFails()
{
using var workspace = TemporaryWorkspace.CreateForCli(outputHelper);
await File.WriteAllTextAsync(Path.Combine(workspace.WorkspaceRoot.FullName, "probe.tape"), "");
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper,
options => options.EnabledFeatures = [KnownFeatures.TerminalCommandsEnabled]);
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper);
using var provider = services.BuildServiceProvider();

var result = provider.GetRequiredService<RootCommand>().Parse("terminal tape play shell --tape-file probe.tape");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public static (ServiceProvider Provider, TestAppHostAuxiliaryBackchannel Backcha

var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, options =>
{
options.EnabledFeatures = [KnownFeatures.TerminalCommandsEnabled];
options.AuxiliaryBackchannelMonitorFactory = _ => monitor;
configureOptions?.Invoke(options);
});
Expand Down
Loading