-
Notifications
You must be signed in to change notification settings - Fork 10
feat: unify prerequisite validation via IRequirementCheck + IPrerequisiteRunner (#106) #312
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
base: main
Are you sure you want to change the base?
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 | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -6,8 +6,10 @@ | |||||||||||||||
| using Microsoft.Extensions.Logging; | ||||||||||||||||
| using Microsoft.Agents.A365.DevTools.Cli.Constants; | ||||||||||||||||
| using Microsoft.Agents.A365.DevTools.Cli.Services.Helpers; | ||||||||||||||||
| using Microsoft.Agents.A365.DevTools.Cli.Exceptions; | ||||||||||||||||
| using Microsoft.Agents.A365.DevTools.Cli.Services; | ||||||||||||||||
| using Microsoft.Agents.A365.DevTools.Cli.Services.Internal; | ||||||||||||||||
| using Microsoft.Agents.A365.DevTools.Cli.Services.Requirements.RequirementChecks; | ||||||||||||||||
| using Microsoft.Agents.A365.DevTools.Cli.Models; | ||||||||||||||||
|
|
||||||||||||||||
| namespace Microsoft.Agents.A365.DevTools.Cli.Commands; | ||||||||||||||||
|
|
@@ -24,7 +26,9 @@ public static Command CreateCommand( | |||||||||||||||
| CommandExecutor executor, | ||||||||||||||||
| AgentBlueprintService agentBlueprintService, | ||||||||||||||||
| IConfirmationProvider confirmationProvider, | ||||||||||||||||
| FederatedCredentialService federatedCredentialService) | ||||||||||||||||
| FederatedCredentialService federatedCredentialService, | ||||||||||||||||
| IPrerequisiteRunner prerequisiteRunner, | ||||||||||||||||
| AzureAuthValidator authValidator) | ||||||||||||||||
| { | ||||||||||||||||
| var cleanupCommand = new Command("cleanup", "Clean up ALL resources (blueprint, instance, Azure) - use subcommands for granular cleanup"); | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -55,7 +59,7 @@ public static Command CreateCommand( | |||||||||||||||
|
|
||||||||||||||||
| // Add subcommands for granular control | ||||||||||||||||
| cleanupCommand.AddCommand(CreateBlueprintCleanupCommand(logger, configService, botConfigurator, executor, agentBlueprintService, confirmationProvider, federatedCredentialService)); | ||||||||||||||||
| cleanupCommand.AddCommand(CreateAzureCleanupCommand(logger, configService, executor)); | ||||||||||||||||
| cleanupCommand.AddCommand(CreateAzureCleanupCommand(logger, configService, executor, prerequisiteRunner, authValidator)); | ||||||||||||||||
| cleanupCommand.AddCommand(CreateInstanceCleanupCommand(logger, configService, executor)); | ||||||||||||||||
|
|
||||||||||||||||
| return cleanupCommand; | ||||||||||||||||
|
|
@@ -304,7 +308,9 @@ private static Command CreateBlueprintCleanupCommand( | |||||||||||||||
| private static Command CreateAzureCleanupCommand( | ||||||||||||||||
| ILogger<CleanupCommand> logger, | ||||||||||||||||
| IConfigService configService, | ||||||||||||||||
| CommandExecutor executor) | ||||||||||||||||
| CommandExecutor executor, | ||||||||||||||||
| IPrerequisiteRunner prerequisiteRunner, | ||||||||||||||||
| AzureAuthValidator authValidator) | ||||||||||||||||
| { | ||||||||||||||||
| var command = new Command("azure", "Remove Azure resources (App Service, App Service Plan)"); | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -331,6 +337,10 @@ private static Command CreateAzureCleanupCommand( | |||||||||||||||
| var config = await LoadConfigAsync(configFile, logger, configService); | ||||||||||||||||
| if (config == null) return; | ||||||||||||||||
|
|
||||||||||||||||
| var authChecks = new List<Services.Requirements.IRequirementCheck> { new AzureAuthRequirementCheck(authValidator) }; | ||||||||||||||||
| if (!await prerequisiteRunner.RunAsync(authChecks, config, logger, CancellationToken.None)) | ||||||||||||||||
| return; | ||||||||||||||||
|
Comment on lines
+341
to
+342
|
||||||||||||||||
| if (!await prerequisiteRunner.RunAsync(authChecks, config, logger, CancellationToken.None)) | |
| return; | |
| if (!await prerequisiteRunner.RunAsync(authChecks, config, logger, CancellationToken.None)) | |
| { | |
| System.Environment.ExitCode = 1; | |
| return; | |
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,6 +7,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||
| using Microsoft.Agents.A365.DevTools.Cli.Models; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| using Microsoft.Agents.A365.DevTools.Cli.Services; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| using Microsoft.Agents.A365.DevTools.Cli.Services.Helpers; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| using Microsoft.Agents.A365.DevTools.Cli.Services.Requirements.RequirementChecks; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| using Microsoft.Extensions.Logging; | ||||||||||||||||||||||||||||||||||||||||||||||||||
| using System.CommandLine; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -19,7 +20,8 @@ public static Command CreateCommand( | |||||||||||||||||||||||||||||||||||||||||||||||||
| IConfigService configService, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| CommandExecutor executor, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| DeploymentService deploymentService, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| IAzureValidator azureValidator, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| IPrerequisiteRunner prerequisiteRunner, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| AzureAuthValidator authValidator, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| GraphApiService graphApiService, | ||||||||||||||||||||||||||||||||||||||||||||||||||
| AgentBlueprintService blueprintService) | ||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -53,7 +55,7 @@ public static Command CreateCommand( | |||||||||||||||||||||||||||||||||||||||||||||||||
| command.AddOption(restartOption); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| // Add subcommands | ||||||||||||||||||||||||||||||||||||||||||||||||||
| command.AddCommand(CreateAppSubcommand(logger, configService, executor, deploymentService, azureValidator)); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| command.AddCommand(CreateAppSubcommand(logger, configService, executor, deploymentService, prerequisiteRunner, authValidator)); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| command.AddCommand(CreateMcpSubcommand(logger, configService, executor, graphApiService, blueprintService)); | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| // Single handler for the deploy command - runs only the application deployment flow | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -82,7 +84,7 @@ public static Command CreateCommand( | |||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| var validatedConfig = await ValidateDeploymentPrerequisitesAsync( | ||||||||||||||||||||||||||||||||||||||||||||||||||
| config.FullName, configService, azureValidator, executor, logger); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| config.FullName, configService, prerequisiteRunner, authValidator, executor, logger); | ||||||||||||||||||||||||||||||||||||||||||||||||||
| if (validatedConfig == null) return; | ||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||
| if (validatedConfig == null) return; | |
| if (validatedConfig == null) | |
| { | |
| System.Environment.ExitCode = 1; | |
| return; | |
| } |
Copilot
AI
Mar 6, 2026
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.
These early-guard failures log an error and then return from the handler, which will likely produce a zero exit code even though the command failed. To make this an actionable early-fail, exit with a non-zero code (e.g., ExceptionHandler.ExitWithCleanup(1) / Environment.Exit(1), or set the invocation exit code) after logging.
| return; | |
| } | |
| if (string.IsNullOrWhiteSpace(updateConfig.AgenticAppId)) | |
| { | |
| logger.LogError("agenticAppId is not configured. Run 'a365 setup all' to complete setup."); | |
| return; | |
| Environment.Exit(1); | |
| } | |
| if (string.IsNullOrWhiteSpace(updateConfig.AgenticAppId)) | |
| { | |
| logger.LogError("agenticAppId is not configured. Run 'a365 setup all' to complete setup."); | |
| Environment.Exit(1); |
Copilot
AI
Mar 6, 2026
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.
Same issue here: logging an error and returning will likely exit with code 0. This should terminate the command with a non-zero exit code so automation/scripts can detect the failure.
| return; | |
| } | |
| if (string.IsNullOrWhiteSpace(updateConfig.AgenticAppId)) | |
| { | |
| logger.LogError("agenticAppId is not configured. Run 'a365 setup all' to complete setup."); | |
| return; | |
| Environment.Exit(1); | |
| } | |
| if (string.IsNullOrWhiteSpace(updateConfig.AgenticAppId)) | |
| { | |
| logger.LogError("agenticAppId is not configured. Run 'a365 setup all' to complete setup."); | |
| Environment.Exit(1); |
Copilot
AI
Mar 6, 2026
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.
The comment says this validates Azure CLI authentication, subscription, and environment, but the current check list only runs AzureAuthRequirementCheck and does not run the AzureEnvironmentValidator anymore. Please update the comment to match the actual behavior (or re-add the environment validation if it’s still intended here).
Copilot
AI
Mar 7, 2026
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.
This auth validation replaced azureValidator.ValidateAllAsync, but it no longer runs the advisory Azure environment validation (Azure CLI architecture/version warnings). If that diagnostic is still useful during deploy, consider invoking IAzureEnvironmentValidator.ValidateEnvironmentAsync() (non-blocking) after auth succeeds.
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.
If the Azure auth prerequisite fails, this handler currently just returns, which will likely result in a zero exit code even though cleanup could not proceed. Consider exiting with a non-zero code (e.g., ExceptionHandler.ExitWithCleanup(1)) after prerequisiteRunner reports failure so scripts can detect the error.