better no-prompt guidance for init and provision - #6962
Conversation
5b3fb43 to
d0fbfb4
Compare
There was a problem hiding this comment.
Pull request overview
Improves non-interactive (--no-prompt) UX by returning actionable, aggregated guidance for init and provision, and by allowing any error to opt into rich terminal/JSON output via ux.UxItem.
Changes:
- Add
Console.IsNoPromptMode()to expose non-interactive mode to components without depending on global flags. - Introduce rich
ux.UxItem-style errors for missing Bicep inputs (provision) and missing init mode (init) with both text and JSON output. - Update UX middleware to render additional
UxItemoutput for errors implementingux.UxItem.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| cli/azd/pkg/input/console.go | Adds IsNoPromptMode() to the Console interface and implements it for AskerConsole. |
| cli/azd/test/mocks/mockinput/mock_console.go | Updates mock console to satisfy the new Console interface method. |
| cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go | Returns a single aggregated “missing inputs” error when in --no-prompt mode. |
| cli/azd/pkg/infra/provisioning/bicep/missing_inputs.go | New rich error type (MissingInputsError) with formatted text + JSON for missing required parameters. |
| cli/azd/pkg/infra/provisioning/bicep/missing_inputs_test.go | New unit tests validating formatted and JSON output for missing-inputs errors. |
| cli/azd/cmd/init.go | Adds InitNoPromptError (rich text + JSON) and returns it when init lacks mode under --no-prompt. |
| cli/azd/cmd/init_test.go | Adds coverage for init --no-prompt requiring an explicit mode. |
| cli/azd/cmd/middleware/ux.go | Enhances middleware to render extra rich output for errors that implement ux.UxItem. |
| cli/azd/extensions/azure.coding-agent/internal/cmd/mocks_azdinput_test.go | Updates generated mock to include IsNoPromptMode() for the updated Console interface. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Victor Vazquez (vhvb1989)
left a comment
There was a problem hiding this comment.
Nothing to block... just an honest concern about the strategy 😆 -
There was a problem hiding this comment.
Code Review — PR #6962
Reviewed with GPT-5.3 Codex and Claude Opus 4.6 in parallel. Consolidated findings below.
🐛 Bug: Resolution step numbering broken when no env vars exist
cli/azd/pkg/infra/provisioning/bicep/missing_inputs.go:93-98
When hasEnvVars() returns false, step 1) is skipped but 2) is unconditionally printed:
You can resolve these by:
2) Setting environment configuration
azd env config set infra.parameters.<paramName> <value>
A 2) with no preceding 1) is confusing. This path fires whenever all missing Bicep parameters lack explicit env var mappings (common for custom params without azd.env metadata).
The existing test TestMissingInputsError_Error_NoEnvVars (line ~90 of missing_inputs_test.go) actually asserts this broken output — it checks "2) Setting environment configuration" is present while "1)" is absent, confirming the numbering is wrong by design.
Suggestion: Either dynamically number the steps with a counter, or switch to unnumbered bullets (matching the • style used elsewhere in the output).
🧪 Test gap: No test for --template flag with --no-prompt
cli/azd/cmd/init_test.go
DoesNotErrorWhenMinimalFlagSet covers --minimal + --no-prompt, but there is no parallel test for --template <id> --environment <env> + --no-prompt. This is the other valid init mode and should be verified to not produce initModeRequiredError.
📋 JSON serialization: empty objects emitted for zero-value fields
cli/azd/pkg/infra/provisioning/bicep/missing_inputs.go:27-33
MissingInput struct tags include json:"secure", json:"description", json:"envVarNames", json:"allowedValues", and json:"constraints" — none with omitempty. This means the JSON output for a simple bool parameter looks like:
{
"name": "flag",
"type": "bool",
"secure": false,
"description": "",
"envVarNames": null,
"configKey": "infra.parameters.flag",
"allowedValues": null,
"constraints": {}
}The null arrays and empty strings add noise for consumers. Consider adding omitempty to optional fields (description, envVarNames, allowedValues, constraints) to keep the JSON output clean — the individual constraint fields already use omitempty correctly.
ℹ️ Nit: Duplicate message string literals
cli/azd/cmd/init.go:920,930 and missing_inputs.go:51,160
The header messages ("Init cannot continue (interactive prompts disabled)", "Provision cannot continue (interactive prompts disabled)") are duplicated between ToString() and MarshalJSON(). Consider extracting to a const to keep them in sync.
The step-numbering bug is the main thing to address before merge.
Wallace Breza (wbreza)
left a comment
There was a problem hiding this comment.
Code Review — PR #6962
Overall Assessment: Comment — Suggest architectural alignment before merge
This is a valuable feature — aggregating all missing inputs into a single actionable error for --no-prompt is a big UX win for CI/CD and agent workflows. The implementation is solid with good test coverage.
Primary recommendation: Align to a single rich error reporting path by extending the existing ErrorWithSuggestion infrastructure rather than creating a parallel UxItem-based error path in the middleware. The codebase already has a well-established pipeline:
error_suggestions.yaml— ~180+ rules matching errors →ErrorWithSuggestionErrorMiddlewarerunserrorPipeline.Process(ctx, err)UxMiddlewarecatchesErrorWithSuggestionand renders viaux.ErrorWithSuggestion(which implementsUxItem)
Suggested approach:
- Extend
ErrorWithSuggestion(or create a newErrorWithDetails) with aDetails UxItemfield for structured rich content - Register error type handlers in the YAML pipeline (e.g.,
errorType: "MissingInputsError"with ahandler) so these errors flow through the same pipeline - This keeps all error-to-user-message logic centralized and discoverable
See inline comments for specific findings.
Findings Summary
| Priority | Count |
|---|---|
| High | 3 |
| Medium | 4 |
| Low | 2 |
| Total | 9 |
✅ What Looks Good
- Aggregating all missing inputs instead of one-at-a-time failures
- Clean
ToString()/MarshalJSON()separation - Thorough test coverage for
MissingInputsError(309 lines) Console.IsNoPromptMode()is a clean abstraction- Mock updates are complete for both
MockConsoleimplementations
d0fbfb4 to
05f253f
Compare
Wallace Breza (wbreza)
left a comment
There was a problem hiding this comment.
Re-Review: PR #6962 — better no-prompt guidance for init and provision
Prior Feedback Status
✅ Step numbering bug — fixed with dynamic optionNum counter
✅ Missing --template test — added DoesNotErrorWhenTemplateAndEnvironmentProvided
✅ JSON omitempty — fixed on optional fields
Great follow-through on the feedback.
Findings Summary
| Priority | Count |
|---|---|
| 🟠 High | 1 |
| 🟡 Medium | 2 |
| 🟢 Low | 1 |
| Total | 4 |
See inline comments for details.
Architectural Note: Error → Suggestion Flow
Reinforcing from prior review — we should ensure a consistent flow for any time we return an error that includes suggestions on how to recover. Today we have ErrorWithSuggestion flowing through error_suggestions.yaml → ErrorMiddleware → UxMiddleware. This PR adds a parallel UxItem-based path in the middleware. As we add more rich error types (agents and CI/CD workflows will surface more of these), having two rendering pipelines will create maintenance burden and inconsistent UX. I'd like to see a follow-up to unify these before adding more error types through this path.
✅ What Looks Good
- Aggregating all missing inputs into a single actionable error is a big UX win for CI/CD and agent workflows
- Good test coverage (380+ test lines) with constraint edge cases and JSON roundtrip validation
Console.IsNoPromptMode()is a clean abstraction with complete mock implementations- Step numbering properly fixed with dynamic counter — good follow-through
Overall Assessment: Comment — The Constraints/omitempty discrepancy between the builder and tests should be addressed. Remaining items are minor.
f08454e to
bc4f2b9
Compare
Azure Dev CLI Install InstructionsInstall scriptsMacOS/Linux
bash: pwsh: WindowsPowerShell install MSI install Standalone Binary
MSI
Documentationlearn.microsoft.com documentationtitle: Azure Developer CLI reference
|
Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com>
* Initial plan * Prepare azure.coding-agent v0.6.1 patch release Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> * Remove #6962 from changelog (test-only changes) Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com>
* Initial plan * Prepare azure.coding-agent v0.6.1 patch release Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> * Remove Azure#6962 from changelog (test-only changes) Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com>
* Initial plan * Prepare azure.coding-agent v0.6.1 patch release Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> * Remove Azure#6962 from changelog (test-only changes) Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com>
* Initial plan * Prepare azure.coding-agent v0.6.1 patch release Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> * Remove Azure#6962 from changelog (test-only changes) Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com>
* Initial plan * Prepare azure.coding-agent v0.6.1 patch release Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> * Remove Azure#6962 from changelog (test-only changes) Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com>
* Initial plan * Prepare azure.coding-agent v0.6.1 patch release Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> * Remove Azure#6962 from changelog (test-only changes) Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com>
* Initial plan * Prepare azure.coding-agent v0.6.1 patch release Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> * Remove Azure#6962 from changelog (test-only changes) Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com>
* Initial plan * Prepare azure.coding-agent v0.6.1 patch release Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> * Remove Azure#6962 from changelog (test-only changes) Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: rajeshkamal5050 <11532743+rajeshkamal5050@users.noreply.github.com>
Summary
When
azdruns with--no-promptand required inputs are missing, it now reports all missing inputs at once with actionable resolution commands — instead of failing one-at-a-time with cryptic prompt errors.azd provision --no-promptWhen required Bicep parameters are missing, the error lists every missing parameter with its environment variable mapping, config key, type, constraints, and allowed values:
With
--output json, the same data is returned as structured JSON with typed constraint fields.azd init --no-promptWhen no mode flag (
--minimal,--template) is provided, the error explains the available options with exact commands:Console.IsNoPromptMode()Exposes whether
--no-promptis active on theConsoleinterface, so any component can detect non-interactive mode without depending onGlobalCommandOptions.UxItem errors attach rich output
The UX middleware now checks whether a returned error implements
ux.UxItem. If it does, the error'sToString()andMarshalJSON()methods are used to render additional structured output after the standardERROR:line. This means any error in the codebase can opt into rich terminal and JSON output simply by implementing theUxIteminterface — no middleware changes required.