fix: switch to foundry backend urls - #9334
Conversation
🔗 Linked Issue RequiredThanks for the contribution! Please link a GitHub issue to this PR by adding |
|
Azure Pipelines: Successfully started running 1 pipeline(s). 21 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
There was a problem hiding this comment.
Pull request overview
Switches the RLE extension to authenticated, project-relative Foundry APIs.
Changes:
- Adds Foundry authentication, API versioning, and new environment/sandbox routes.
- Adds disk-image conversion polling and updates invocation behavior.
- Bumps the preview version and refreshes documentation.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
version.txt |
Bumps version to 0.2.0-preview. |
README.md |
Documents Foundry setup and workflows. |
internal/project/docker.go |
Clarifies ACR login guidance. |
internal/cmd/invoke.go |
Updates sandbox lifecycle and polling. |
internal/cmd/invoke_test.go |
Tests new invocation routes. |
internal/cmd/deploy.go |
Deploys through the Foundry endpoint. |
internal/cmd/client.go |
Adds authenticated Foundry API client. |
internal/cmd/client_test.go |
Tests authentication and endpoints. |
go.mod |
Promotes Azure identity dependencies. |
extension.yaml |
Updates extension version. |
CHANGELOG.md |
Adds 0.2.0-preview notes. |
Comments suppressed due to low confidence (1)
cli/azd/extensions/azure.ai.rle/internal/cmd/client_test.go:80
- azd-code-reviewer: Use
t.Context()for test I/O so the request is canceled if the test ends, as required by the repository's Go 1.26 test pattern (cli/azd/AGENTS.md:356).
err := client.do(context.Background(), http.MethodGet, environmentCollectionPath, nil, nil)
Validate persisted Foundry endpoints before creating credentials and cover the full project-relative route shape in invoke tests. Correct the release heading, prerequisites, and test contexts. Authored-by: GitHub Copilot CLI v1.0.68 Model: GPT-5.4 (gpt-5.4) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (5)
cli/azd/extensions/azure.ai.rle/internal/cmd/client.go:228
- azd-code-reviewer:
GetTokenfailures are local authentication failures, but both callers wrap this error withserviceError, labeling itrle-control-planeand suggesting that the endpoint is unreachable. A signed-out user therefore gets the wrong remediation. Return a distinct local authentication error withaz login/azd auth loginguidance before the generic service-error path;azdext.ServiceErroris reserved for HTTP/gRPC service failures (cli/azd/pkg/azdext/extension_error.go:15-16).
token, err := c.credential.GetToken(ctx, policy.TokenRequestOptions{
Scopes: []string{foundryTokenScope},
})
if err != nil {
return fmt.Errorf("authenticate to Foundry: %w", err)
cli/azd/extensions/azure.ai.rle/internal/cmd/invoke.go:98
- azd-code-reviewer: Removing the playground URL makes the browser-launch warning below non-actionable: on headless or SSH systems, users can no longer open the UI manually. Keep the raw sandbox URL hidden, but provide a safe fallback such as a localhost proxy URL or an actionable command when
OpenBrowserfails.
"Sandbox %s ready\n",
sandbox.Id,
cli/azd/extensions/azure.ai.rle/internal/cmd/deploy.go:116
- azd-code-reviewer: Both branches call the same API, so this condition implies create/update behavior that does not exist and can drift later. Collapse it to one call.
if state.EnvironmentId == "" {
environment, err = client.createV1Environment(a.cmd.Context(), request)
} else {
environment, err = client.createV1Environment(a.cmd.Context(), request)
}
cli/azd/extensions/azure.ai.rle/README.md:159
- The code now intentionally falls back to the project endpoint saved in
.azd-rle.jsonwhenFOUNDRY_PROJECT_ENDPOINTis unset, but this says deploy always reads the environment variable. Document the fallback and precedence so users know which Foundry project will receive the deployment.
Deploy reads the Foundry project endpoint from `FOUNDRY_PROJECT_ENDPOINT` and the ACR registry from `AZURE_CONTAINER_REGISTRY_ENDPOINT`. It derives the project route segment from `/api/projects/<project>`, builds the Docker image as `<registry>.azurecr.io/<project>-<environment>:latest`, pushes it to ACR, registers that image by calling `<FOUNDRY_PROJECT_ENDPOINT>/fine_tuning/environments`, and saves the project/environment details in `.azd-rle.json`.
cli/azd/extensions/azure.ai.rle/internal/cmd/client.go:88
- This remediation assumes the endpoint came from
FOUNDRY_PROJECT_ENDPOINT, but deploy can now use the value saved in.azd-rle.json. Refer to the configured endpoint generically and explain that the environment variable overrides it; otherwise the message points users at an unset variable.
This issue also appears on line 224 of the same file.
Suggestion: fmt.Sprintf(
"Ensure the Foundry project endpoint in %s is reachable and enabled for RLE.",
foundryProjectEndpointEnvVar,
),
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (5)
cli/azd/extensions/azure.ai.rle/internal/cmd/client.go:95
normalizeFoundryProjectEndpointcurrently accepts paths with extra segments after/api/projects/<project>. That was mostly harmless when only the project segment was extracted, but this client now uses the whole normalized value as its base URL, so an endpoint such as.../api/projects/p/extrasends every request under/extra/fine_tuning/...and fails with a service error instead of being rejected. Require the project endpoint path to end after the project segment before using it as the base URL.
func newRleClient(endpoint string) (*rleClient, error) {
normalizedEndpoint, err := normalizeFoundryProjectEndpoint(endpoint)
if err != nil {
return nil, err
cli/azd/extensions/azure.ai.rle/internal/cmd/run.go:194
- Removing the runtime override disables
/webfor valid OpenEnv images whose Dockerfile defaultsENABLE_WEB_INTERFACE=false(for example, upstreamgrid_world_envanddipg_safety_env).runstill always opens and documents/web, so those environments now launch a missing playground. Keep passingENABLE_WEB_INTERFACE=trueto preserve the command's behavior.
"-p", portMapping,
image,
cli/azd/extensions/azure.ai.rle/internal/cmd/client.go:228
- A token acquisition failure is returned as an ordinary client error, so both
deployandinvokewrap it withserviceError. This reportsrle-control-planeas the failing service and suggests checking the endpoint even though no request was sent; users who need to sign in or select a credential get misleading recovery guidance. Preserve a distinct auth/local error here and avoid wrapping it as a service response.
token, err := c.credential.GetToken(ctx, policy.TokenRequestOptions{
Scopes: []string{foundryTokenScope},
})
if err != nil {
return fmt.Errorf("authenticate to Foundry: %w", err)
cli/azd/extensions/azure.ai.rle/internal/cmd/invoke.go:98
- The sandbox URL is hidden on the success path, but it is still exposed on failures.
project.WaitForHealthincludesbaseUrlin its timeout error, andRunShellWithContextincludes the full request URL on transport errors, soinvokecan print the data-plane URL whenever health or a shell request fails. Redact or replace those errors on the remote path to satisfy the stated URL-hiding behavior.
sandboxUrl := strings.TrimRight(sandbox.BaseUrl, "/")
if _, err := fmt.Fprintf(
a.cmd.OutOrStdout(),
"Sandbox %s ready\n",
sandbox.Id,
cli/azd/extensions/azure.ai.rle/internal/cmd/invoke.go:178
- The new 15-minute polling loop aborts on the first transient GET failure. Because this client has no Azure SDK retry policy, a temporary network error, 429, or 5xx during image conversion ends
invokeeven though conversion may still be progressing. Retry transient failures within the existing deadline (while still returning permanent 4xx responses) so the asynchronous wait is resilient.
deadline := time.Now().Add(remoteImageConversionTimeout)
for {
environment, err := client.getEnvironmentVersion(ctx, state.Name, state.EnvironmentVersion)
if err != nil {
return err
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (3)
cli/azd/extensions/azure.ai.rle/internal/cmd/client.go:228
- Authentication failures here are later passed through
serviceErrorby both deploy and invoke, so they become anazdext.ServiceErrorattributed torle-control-planewith advice to check the endpoint.GetTokenfails locally before any service call, making the telemetry attribution and remediation incorrect. Preserve credential failures as a local authentication error (withaz login/azd auth loginguidance), and reserveServiceErrorfor an actual HTTP response. (azd-code-reviewer)
token, err := c.credential.GetToken(ctx, policy.TokenRequestOptions{
Scopes: []string{foundryTokenScope},
})
if err != nil {
return fmt.Errorf("authenticate to Foundry: %w", err)
cli/azd/extensions/azure.ai.rle/internal/cmd/invoke.go:94
- The sandbox URL is still exposed on failure paths despite the PR's promise to keep it out of terminal output.
project.WaitForHealthincludesbaseUrlin its returned error (runtime.go:145), andRunShellWithContextprints request errors containing the full URL (runtime.go:175-177). A health timeout or transient shell request failure will therefore reveal the data-plane proxy URL. Add a remote-sandbox redaction path so these helpers never render this URL. (azd-code-reviewer)
sandboxUrl := strings.TrimRight(sandbox.BaseUrl, "/")
cli/azd/extensions/azure.ai.rle/internal/cmd/run.go:194
- Removing this override breaks
run's documented promise to open/webfor custom OpenEnv images. OpenEnv's web UI is off by default unlessENABLE_WEB_INTERFACE=true, and current upstream images such asgrid_world_envanddipg_safety_envexplicitly bake infalse; those containers will remain healthy, but the browser opens a missing UI. Keep the runtime override soazd ai rle runconsistently enables the playground. (azd-code-reviewer)
"run", "-d",
"--name", container,
"--label", localContainerImageLabel + "=" + image,
"-p", portMapping,
image,
| "url": "https://github.com/Azure/azure-dev/releases/download/azd-ext-azure-ai-rle_0.1.0-preview/azure-ai-rle-windows-arm64.zip" | ||
| } | ||
| } | ||
| }, |
There was a problem hiding this comment.
The shouldn't be updated manually, it will be updated via the dev registry release pipeline
Changes: