Skip to content

Commit 9a710fe

Browse files
Copilotvhvb1989JeffreyCAazure-sdkbwateratmsft
authored
Add external prompting support to Azure Developer CLI (#6605)
* fix security issue with playwright/test 1.49.1 (#6592) * Checkpoint from VS Code for cloud agent session * Update parameter popup border color to cyan in concurX extension Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> * Complete concurX parameter popup color update Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> * cspell * Remove unintended changes to azure.ai.finetune extension Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> * azure.ai.agents - Set `CGO_ENABLED=0` for x64 Linux build (#6611) * Set CGO_ENABLED=0 for x64 Linux build * Bump version * Bump version to 0.1.8-preview (#6613) * Extension update fixes/enhancements (#6604) * Clarify extension list latest version column * Add update availability JSON property and show asterisk besides outdated extensions * Add upgrade hints to extension list output * Fix cooldown logic and shallow copy * Update AGENTS.md --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JeffreyCA <9157833+JeffreyCA@users.noreply.github.com> * Fix bicep CLI uninitialized path in container app deployments (#6610) * fix security issue with playwright/test 1.49.1 (#6592) * Checkpoint from VS Code for cloud agent session * Fix bicep CLI initialization by restoring EnsureInstalled calls - Restore public EnsureInstalled() method in bicep.go - Remove automatic installation from Build() and BuildBicepParam() - Add explicit EnsureInstalled() calls in service_target_containerapp.go and bicep_provider.go - Update all test files to use public EnsureInstalled() method - Reverts incorrect changes from previous checkpoint commit This fix follows the same pattern as PR #6593 for GitHub CLI. Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> * Checkpoint from VS Code for cloud agent session --------- Co-authored-by: Victor Vazquez <vhvb1989@gmail.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> * Add azure.ai.agent 0.1.8-preview to registry (#6615) * Release 1.23.2 (#6616) * Initial plan * Release 1.23.2 Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> * Increment CLI version after release (#6617) * Migrate to use new shared eng package (#6600) * Fix VS Code extension commands failing with undefined fsPath in virtual file systems (#6601) * Initial plan * Add defensive checks for undefined fsPath in VS Code extension commands This fixes the issue where provision and other commands would fail with "The 'path' argument must be of type string. Received undefined" when used with virtual file systems or certain VS Code contexts. Changes: - Added validation for selectedFile.fsPath before calling getWorkingFolder - Provides clear error messages that include URI scheme and selectedItem type - Suppresses automatic issue reporting since this is a user error - Applied fix to all affected commands: provision, deploy, up, down, restore, monitor, packageCli, and pipelineConfig - Added unit tests for the new validation logic Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> * Simplify provision.test.ts based on code review feedback Removed unused stub functions that weren't actually being used. Simplified tests to focus on the core validation logic. Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> * Refactor validation logic into shared utility function Based on code review feedback: - Extracted duplicated validation logic to validateFileSystemUri() in cmdUtil.ts - Updated all 8 command files to use the shared function - Simplified test assertions - Improved code maintainability by reducing duplication Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> * Fix validation to use strict equality check for undefined Changed condition from `!selectedFile.fsPath` to `selectedFile.fsPath === undefined` to avoid incorrectly rejecting empty string paths which are valid for root directories. Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> * Fix l10n.t() to use single string literal instead of concatenation The first argument to vscode.l10n.t() should be a single string literal for proper localization tooling compatibility. Removed string concatenation and used a single multi-line string literal instead. Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> * Add missing keys to `azd config options` (#6619) * Add missing config options --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JeffreyCA <9157833+JeffreyCA@users.noreply.github.com> * Raising for missing method type (#6628) * adding project-endpoint to init command * adding 12 preview release * fixig default customization method & adding training type * correct version * RFT grader fixes (#6629) * adding project-endpoint to init command * adding 12 preview release * fixig default customization method & adding training type * correct version * adding grader to cloning code * adding missing grader functionality * merging master * including .14-preview to main registry (#6630) * Add a naive attempt at downloading manifest (#6631) * Add a naive attempt at downloading * Address PR comments Signed-off-by: trangevi <trangevi@microsoft.com> * Update download directory as well Signed-off-by: trangevi <trangevi@microsoft.com> * Use net/url parsing in parseGitHubUrlNaive to handle fragments and query params (#6634) * Initial plan * Use net/url parsing to handle query params and fragments in parseGitHubUrlNaive Co-authored-by: trangevi <26490000+trangevi@users.noreply.github.com> * Final review completed Co-authored-by: trangevi <26490000+trangevi@users.noreply.github.com> * Revert unintended changes to other extensions Co-authored-by: trangevi <26490000+trangevi@users.noreply.github.com> * Address PR comments Signed-off-by: trangevi <trangevi@microsoft.com> * Update download directory as well Signed-off-by: trangevi <trangevi@microsoft.com> * Initial plan * Rebased on latest base branch --------- Signed-off-by: trangevi <trangevi@microsoft.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: trangevi <26490000+trangevi@users.noreply.github.com> Co-authored-by: trangevi <trangevi@microsoft.com> --------- Signed-off-by: trangevi <trangevi@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: trangevi <26490000+trangevi@users.noreply.github.com> * Dev container feature - allow installing extensions (#6460) * Add extensions option to the azd devcontainer feature to allow specifying extensions to install * Review updates * Revert whitespace changes * Address feedback on shell script. Add multiple extensions to the test config to validate * Enable full figspec generation for extensions with metadata capability (#6620) * Fix indentation * Add metadata capability checks and improve error handling * Support dynamic suggestions for `azd config` commands * Exclude global persistent flags --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: JeffreyCA <9157833+JeffreyCA@users.noreply.github.com> * Add concurX binary to gitignore Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> * lint * Update TestAskerConsoleExternalPrompt to use new external prompt mechanism Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> --------- Signed-off-by: trangevi <trangevi@microsoft.com> Co-authored-by: Victor Vazquez <vhvb1989@gmail.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com> Co-authored-by: JeffreyCA <jeffreychen@microsoft.com> Co-authored-by: JeffreyCA <9157833+JeffreyCA@users.noreply.github.com> Co-authored-by: Azure SDK Bot <53356347+azure-sdk@users.noreply.github.com> Co-authored-by: Brandon Waterloo [MSFT] <36966225+bwateratmsft@users.noreply.github.com> Co-authored-by: Amit Chauhan <70937115+achauhan-scc@users.noreply.github.com> Co-authored-by: Travis Angevine <trangevi@microsoft.com> Co-authored-by: trangevi <26490000+trangevi@users.noreply.github.com> Co-authored-by: Stuart Leeks <stuartle@microsoft.com>
1 parent 552a595 commit 9a710fe

File tree

14 files changed

+1607
-55
lines changed

14 files changed

+1607
-55
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,6 @@ cli/azd/extensions/microsoft.azd.concurx/microsoft.azd.concurx
7171
cli/azd/extensions/microsoft.azd.concurx/microsoft.azd.concurx.exe
7272
cli/azd/azd-test
7373
cli/azd/azd
74+
cli/azd/extensions/microsoft.azd.concurx/concurx
75+
cli/azd/extensions/microsoft.azd.concurx/concurx
76+
cli/azd/extensions/microsoft.azd.concurx/concurx.exe

cli/azd/.vscode/cspell.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,9 @@ overrides:
312312
- filename: extensions/microsoft.azd.demo/internal/cmd/metadata.go
313313
words:
314314
- invopop
315+
- filename: extensions/microsoft.azd.concurx/internal/cmd/prompt_model.go
316+
words:
317+
- textinput
315318
ignorePaths:
316319
- "**/*_test.go"
317320
- "**/mock*.go"

cli/azd/cmd/container.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,24 @@ func registerCommonDependencies(container *ioc.NestedContainer) {
135135
isTerminal := cmd.OutOrStdout() == os.Stdout &&
136136
cmd.InOrStdin() == os.Stdin && terminal.IsTerminal(os.Stdout.Fd(), os.Stdin.Fd())
137137

138+
// Check for external prompt configuration from environment variables
139+
var externalPromptCfg *input.ExternalPromptConfiguration
140+
if endpoint := os.Getenv("AZD_UI_PROMPT_ENDPOINT"); endpoint != "" {
141+
if key := os.Getenv("AZD_UI_PROMPT_KEY"); key != "" {
142+
externalPromptCfg = &input.ExternalPromptConfiguration{
143+
Endpoint: endpoint,
144+
Key: key,
145+
Transporter: http.DefaultClient,
146+
NoPromptDialog: os.Getenv("AZD_UI_NO_PROMPT_DIALOG") != "",
147+
}
148+
}
149+
}
150+
138151
return input.NewConsole(rootOptions.NoPrompt, isTerminal, input.Writers{Output: writer}, input.ConsoleHandles{
139152
Stdin: cmd.InOrStdin(),
140153
Stdout: cmd.OutOrStdout(),
141154
Stderr: cmd.ErrOrStderr(),
142-
}, formatter, nil)
155+
}, formatter, externalPromptCfg)
143156
})
144157

145158
container.MustRegisterSingleton(
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package cmd
5+
6+
import (
7+
"encoding/json"
8+
"net/http"
9+
"net/http/httptest"
10+
"os"
11+
"testing"
12+
13+
"github.com/azure/azure-dev/cli/azd/internal"
14+
"github.com/azure/azure-dev/cli/azd/pkg/input"
15+
"github.com/azure/azure-dev/cli/azd/pkg/output"
16+
"github.com/spf13/cobra"
17+
"github.com/stretchr/testify/require"
18+
)
19+
20+
// TestExternalPromptFromEnvironmentVariables verifies that the console reads
21+
// AZD_UI_PROMPT_ENDPOINT and AZD_UI_PROMPT_KEY environment variables and
22+
// configures external prompting accordingly.
23+
func TestExternalPromptFromEnvironmentVariables(t *testing.T) {
24+
// Create a test HTTP server that simulates the external prompt endpoint
25+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
26+
// Return a success response
27+
w.Header().Set("Content-Type", "application/json")
28+
json.NewEncoder(w).Encode(map[string]any{
29+
"status": "success",
30+
"value": "test-response",
31+
})
32+
}))
33+
defer server.Close()
34+
35+
testKey := "test-secret-key-12345"
36+
37+
// Set environment variables
38+
t.Setenv("AZD_UI_PROMPT_ENDPOINT", server.URL)
39+
t.Setenv("AZD_UI_PROMPT_KEY", testKey)
40+
41+
// Create a mock cobra command
42+
cmd := &cobra.Command{}
43+
cmd.SetIn(os.Stdin)
44+
cmd.SetOut(os.Stdout)
45+
cmd.SetErr(os.Stderr)
46+
47+
// Create root options
48+
rootOptions := &internal.GlobalCommandOptions{
49+
NoPrompt: false,
50+
}
51+
52+
// Create formatter
53+
var formatter output.Formatter = nil
54+
55+
// This simulates what happens in container.go when registering the console
56+
writer := cmd.OutOrStdout()
57+
58+
isTerminal := false // Force non-terminal for test
59+
60+
// Check for external prompt configuration from environment variables
61+
// (This is the code we added to container.go)
62+
var externalPromptCfg *input.ExternalPromptConfiguration
63+
if endpoint := os.Getenv("AZD_UI_PROMPT_ENDPOINT"); endpoint != "" {
64+
if key := os.Getenv("AZD_UI_PROMPT_KEY"); key != "" {
65+
externalPromptCfg = &input.ExternalPromptConfiguration{
66+
Endpoint: endpoint,
67+
Key: key,
68+
Transporter: http.DefaultClient,
69+
}
70+
}
71+
}
72+
73+
// Verify the config was created
74+
require.NotNil(t, externalPromptCfg, "External prompt config should be created from env vars")
75+
require.Equal(t, server.URL, externalPromptCfg.Endpoint)
76+
require.Equal(t, testKey, externalPromptCfg.Key)
77+
require.NotNil(t, externalPromptCfg.Transporter)
78+
79+
// Create the console with external prompting configured
80+
console := input.NewConsole(
81+
rootOptions.NoPrompt,
82+
isTerminal,
83+
input.Writers{Output: writer},
84+
input.ConsoleHandles{
85+
Stdin: cmd.InOrStdin(),
86+
Stdout: cmd.OutOrStdout(),
87+
Stderr: cmd.ErrOrStderr(),
88+
},
89+
formatter,
90+
externalPromptCfg,
91+
)
92+
93+
require.NotNil(t, console)
94+
95+
// Note: Actually testing that the console uses external prompting would require
96+
// calling Prompt/Select/Confirm methods, which is tested in console_test.go
97+
// This test verifies the environment variable reading logic works correctly.
98+
}
99+
100+
// TestExternalPromptNotConfiguredWithoutEnvVars verifies that when the
101+
// environment variables are not set, no external prompt config is created.
102+
func TestExternalPromptNotConfiguredWithoutEnvVars(t *testing.T) {
103+
// Ensure env vars are not set
104+
os.Unsetenv("AZD_UI_PROMPT_ENDPOINT")
105+
os.Unsetenv("AZD_UI_PROMPT_KEY")
106+
107+
// Check for external prompt configuration from environment variables
108+
var externalPromptCfg *input.ExternalPromptConfiguration
109+
if endpoint := os.Getenv("AZD_UI_PROMPT_ENDPOINT"); endpoint != "" {
110+
if key := os.Getenv("AZD_UI_PROMPT_KEY"); key != "" {
111+
externalPromptCfg = &input.ExternalPromptConfiguration{
112+
Endpoint: endpoint,
113+
Key: key,
114+
Transporter: http.DefaultClient,
115+
}
116+
}
117+
}
118+
119+
require.Nil(t, externalPromptCfg, "External prompt config should be nil when env vars not set")
120+
}
121+
122+
// TestExternalPromptRequiresBothEnvVars verifies that both environment
123+
// variables must be set for external prompting to be configured.
124+
func TestExternalPromptRequiresBothEnvVars(t *testing.T) {
125+
t.Run("only endpoint set", func(t *testing.T) {
126+
t.Setenv("AZD_UI_PROMPT_ENDPOINT", "http://localhost:8080")
127+
os.Unsetenv("AZD_UI_PROMPT_KEY")
128+
129+
var externalPromptCfg *input.ExternalPromptConfiguration
130+
if endpoint := os.Getenv("AZD_UI_PROMPT_ENDPOINT"); endpoint != "" {
131+
if key := os.Getenv("AZD_UI_PROMPT_KEY"); key != "" {
132+
externalPromptCfg = &input.ExternalPromptConfiguration{
133+
Endpoint: endpoint,
134+
Key: key,
135+
Transporter: http.DefaultClient,
136+
}
137+
}
138+
}
139+
140+
require.Nil(t, externalPromptCfg, "Config should be nil when only endpoint is set")
141+
})
142+
143+
t.Run("only key set", func(t *testing.T) {
144+
os.Unsetenv("AZD_UI_PROMPT_ENDPOINT")
145+
t.Setenv("AZD_UI_PROMPT_KEY", "secret-key")
146+
147+
var externalPromptCfg *input.ExternalPromptConfiguration
148+
if endpoint := os.Getenv("AZD_UI_PROMPT_ENDPOINT"); endpoint != "" {
149+
if key := os.Getenv("AZD_UI_PROMPT_KEY"); key != "" {
150+
externalPromptCfg = &input.ExternalPromptConfiguration{
151+
Endpoint: endpoint,
152+
Key: key,
153+
Transporter: http.DefaultClient,
154+
}
155+
}
156+
}
157+
158+
require.Nil(t, externalPromptCfg, "Config should be nil when only key is set")
159+
})
160+
}

0 commit comments

Comments
 (0)