Skip to content

fix: switch to foundry backend urls - #9334

Open
farhann1 wants to merge 4 commits into
mainfrom
farhannawaz/rle-control-plane
Open

fix: switch to foundry backend urls#9334
farhann1 wants to merge 4 commits into
mainfrom
farhannawaz/rle-control-plane

Conversation

@farhann1

@farhann1 farhann1 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Changes:

  • Switch RLE environment and sandbox APIs to Foundry project-relative endpoints.
  • Authenticate requests using Azure credentials and the Foundry token scope.
  • Add environment versioning and asynchronous image-conversion polling.
  • Update sandbox lease, status, and release handling.
  • Keep sandbox data-plane proxy URLs hidden from terminal output.
  • Update documentation and tests for the new workflow.

Copilot AI review requested due to automatic review settings July 28, 2026 14:25
@github-actions

Copy link
Copy Markdown

🔗 Linked Issue Required

Thanks for the contribution! Please link a GitHub issue to this PR by adding Fixes #123 to the description or using the sidebar.
No issue yet? Feel free to create one!

@azure-pipelines

Copy link
Copy Markdown
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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/client.go
Comment thread cli/azd/extensions/azure.ai.rle/CHANGELOG.md Outdated
Comment thread cli/azd/extensions/azure.ai.rle/README.md Outdated
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/client.go Outdated
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/invoke_test.go Outdated
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/client_test.go Outdated
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>
Copilot AI review requested due to automatic review settings July 29, 2026 07:51
@farhann1 farhann1 changed the title fix: switch to foundry auth and backend urls fix: switch to foundry backend urls Jul 29, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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: GetToken failures are local authentication failures, but both callers wrap this error with serviceError, labeling it rle-control-plane and suggesting that the endpoint is unreachable. A signed-out user therefore gets the wrong remediation. Return a distinct local authentication error with az login/azd auth login guidance before the generic service-error path; azdext.ServiceError is 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 OpenBrowser fails.
		"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.json when FOUNDRY_PROJECT_ENDPOINT is 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,
		),

Copilot AI review requested due to automatic review settings July 29, 2026 11:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

  • normalizeFoundryProjectEndpoint currently 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/extra sends 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 /web for valid OpenEnv images whose Dockerfile defaults ENABLE_WEB_INTERFACE=false (for example, upstream grid_world_env and dipg_safety_env). run still always opens and documents /web, so those environments now launch a missing playground. Keep passing ENABLE_WEB_INTERFACE=true to 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 deploy and invoke wrap it with serviceError. This reports rle-control-plane as 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.WaitForHealth includes baseUrl in its timeout error, and RunShellWithContext includes the full request URL on transport errors, so invoke can 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 invoke even 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

Copilot AI review requested due to automatic review settings July 29, 2026 11:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 serviceError by both deploy and invoke, so they become an azdext.ServiceError attributed to rle-control-plane with advice to check the endpoint. GetToken fails locally before any service call, making the telemetry attribution and remediation incorrect. Preserve credential failures as a local authentication error (with az login/azd auth login guidance), and reserve ServiceError for 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.WaitForHealth includes baseUrl in its returned error (runtime.go:145), and RunShellWithContext prints 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 /web for custom OpenEnv images. OpenEnv's web UI is off by default unless ENABLE_WEB_INTERFACE=true, and current upstream images such as grid_world_env and dipg_safety_env explicitly bake in false; those containers will remain healthy, but the browser opens a missing UI. Keep the runtime override so azd ai rle run consistently 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"
}
}
},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The shouldn't be updated manually, it will be updated via the dev registry release pipeline

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ext-rle azure.ai.rle extension

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants