Skip to content

feat: ai rle v1#8782

Open
farhann1 wants to merge 25 commits into
Azure:mainfrom
farhann1:farhannawaz/rle-cli
Open

feat: ai rle v1#8782
farhann1 wants to merge 25 commits into
Azure:mainfrom
farhann1:farhannawaz/rle-cli

Conversation

@farhann1

@farhann1 farhann1 commented Jun 23, 2026

Copy link
Copy Markdown

Summary

Adds the preview azd ai rle extension for source-first RLE/OpenEnv environment workflows.

The extension supports initializing an OpenEnv-style sample, running it locally in Docker, deploying/registering it with the RLE control plane, and invoking a remote sandbox for interactive testing.

Changes

  • Added hidden preview command group gated by AZD_AI_RLE_ENABLE=true.
  • Added azd ai rle init [environment-name] to copy the default OpenEnv echo sample and create .azd-rle.json.
  • Added azd ai rle run for local Docker build/run, /health readiness, /web launch, OpenEnv shell, and optional --watch.
  • Added azd ai rle deploy to build/push an ACR image and create/update the RLE environment.
  • Added azd ai rle invoke to lease a remote sandbox, open the sandbox/proxy UI, start the OpenEnv shell, and release the sandbox on exit.
  • Added minimal local state using name, project, environmentId, and environmentVersion.
  • Added README guidance for local setup, environment variables, Dockerfile discovery, deploy image naming, and command usage.

Notes

  • This is an internal preview surface and commands are hidden unless AZD_AI_RLE_ENABLE=true.
  • RLE control plane endpoint is configured with RLE_ENDPOINT and defaults to http://localhost:5000.
  • Deploy uses AZURE_CONTAINER_REGISTRY_ENDPOINT and publishes images as <registry>/<project-id>-<environment>:latest.

Validation

  • go test .\internal\cmd
  • go build -o bin\azure-ai-rle-windows-amd64.exe .
  • cspell lint 'extensions/**/*.go' 'extensions/**/*.md' --config ./.vscode/cspell.yaml --no-progress
  • git diff --check

Copilot AI review requested due to automatic review settings June 23, 2026 12:13
@microsoft-github-policy-service microsoft-github-policy-service Bot added the customer-reported identify a customer issue label Jun 23, 2026
@microsoft-github-policy-service

Copy link
Copy Markdown
Contributor

Thank you for your contribution @farhann1! We will review the pull request and get back to you soon.

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

Adds a new first-party azure.ai.rle azd extension scaffold, establishing the initial command surface area and packaging/build plumbing so the extension can be built, packed, and tested prior to implementing the real RLE workflow.

Changes:

  • Introduces the azd ai rle command group with create, modify, version, and hidden metadata commands (stubbed with structured “not implemented” errors).
  • Adds extension packaging metadata (extension.yaml, version.txt, CHANGELOG.md) plus docs and lint/spellcheck configs for the new module.
  • Adds cross-platform build scripts and the Go module (go.mod/go.sum) for the extension.

Reviewed changes

Copilot reviewed 17 out of 18 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
cli/azd/extensions/azure.ai.rle/version.txt Declares initial extension version.
cli/azd/extensions/azure.ai.rle/README.md Documents commands and private testing workflow.
cli/azd/extensions/azure.ai.rle/main.go Extension entrypoint wiring azdext.Run to the root command.
cli/azd/extensions/azure.ai.rle/internal/cmd/root.go Root command setup and subcommand registration.
cli/azd/extensions/azure.ai.rle/internal/cmd/create.go Adds create command stub + shared not-implemented error helper.
cli/azd/extensions/azure.ai.rle/internal/cmd/modify.go Adds modify command stub.
cli/azd/extensions/azure.ai.rle/internal/cmd/version.go Adds version command wiring for standard version output.
cli/azd/extensions/azure.ai.rle/internal/cmd/metadata.go Adds hidden metadata command for discovery/IntelliSense.
cli/azd/extensions/azure.ai.rle/internal/cmd/root_test.go Basic test asserting expected commands are registered.
cli/azd/extensions/azure.ai.rle/go.mod New Go module for the extension and dependency set.
cli/azd/extensions/azure.ai.rle/go.sum Dependency checksums for the new module.
cli/azd/extensions/azure.ai.rle/extension.yaml Extension manifest (id/namespace/usage/examples/version).
cli/azd/extensions/azure.ai.rle/cspell.yaml Extension-local cspell configuration.
cli/azd/extensions/azure.ai.rle/CHANGELOG.md Initial changelog entry for the preview scaffold.
cli/azd/extensions/azure.ai.rle/build.sh Bash build script for multi-platform binaries + ldflags version injection.
cli/azd/extensions/azure.ai.rle/build.ps1 PowerShell build script for multi-platform binaries + ldflags version injection.
cli/azd/extensions/azure.ai.rle/.golangci.yaml Extension-local lint config (matching other extensions’ pattern).
cli/azd/extensions/azure.ai.rle/.gitignore Ignores build and packaging artifact directories.

Comment thread cli/azd/extensions/azure.ai.rle/build.ps1 Outdated

@jongio jongio left a comment

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.

Review: azure.ai.rle extension (new)

Thanks for contributing a new extension! A few items to address before this is ready.

Overview

This adds a new azd ai rle command group for managing RLE (Reinforcement Learning Environment) resources. The implementation is clean and follows the extension SDK patterns well. Tests pass and it builds cleanly.

Key items

  1. Missing PR description. A 2949-line new extension needs a description explaining what RLE is, the motivation, the commands it adds, and any design decisions. Right now the body is empty.

  2. Unreachable code. Five files define commands (create, list, show, sandbox, versions) that are never registered in root.go. These add ~500 lines of untestable surface area. Either wire them up (if intended for this PR) or remove them and add in a follow-up when they're needed.

  3. Cross-platform line endings. scaffold.go:67 unconditionally converts \n to \r\n. Generated Dockerfiles and Python files will have Windows line endings on Linux/macOS, which can cause issues with container builds and shebangs.

  4. Unquoted paths in user-facing output. init.go:55 prints cd %s without quoting. Paths containing spaces will break the suggested command. This repo's conventions require quoting paths (see AGENTS.md).

  5. Bearer token over HTTP. The client sends RLE_BEARER_TOKEN regardless of the endpoint scheme. Consider logging a warning (or refusing) when sending credentials over non-TLS connections to non-localhost endpoints.

See inline comments for specifics.

Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/root.go
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/scaffold.go Outdated
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/init.go Outdated
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/client.go Outdated

@jongio jongio left a comment

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.

Incremental review (commit d621e52)

New deploy enhancements look well-structured. The splitImageHost/normalizeRegistryLoginServer composition is clean, and using errors.AsType for the 404 check is idiomatic Go 1.26. A few items:

Previous review items (5 findings from my earlier pass) are still unresolved: unreachable command constructors, cross-platform line endings in scaffold.go, unquoted paths in init.go, bearer token over HTTP. Please address those alongside the new work.

Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/deploy.go Outdated
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/deploy.go
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/deploy.go Outdated

@jongio jongio left a comment

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.

Incremental review (commits 9dc600d, 6772f58)

The invoke implementation is taking shape. The approach of fetching Loom via shallow clone plus bundled wheel is reasonable for a dev workflow. A few items need attention before this can merge.

Prior review items: 3 of 5 findings from my earlier passes remain unresolved (unreachable command constructors in root.go, cross-platform CRLF in scaffold.go, unquoted path in init.go). The bearer-token item was addressed by removal.

New findings (this commit):

  1. Binary wheel without provenance (assets/rle_sdk-0.1.3-py3-none-any.whl): Committing a pre-built .whl makes the package un-auditable. Add a README or comment documenting where this wheel is built, what source repo/tag it corresponds to, and how a reviewer can reproduce it. Alternatively, reference a published package feed so CI can fetch it at build time instead of vendoring the binary.

  2. Deploy ignores stored endpoint (deploy.go): resolveControlPlaneEndpoint("") replaced resolveControlPlaneEndpoint(state.Endpoint). If a user had an endpoint saved in .azd-rle.json from the manifest, it's now silently ignored. Was this intentional? If so, note it in the changelog.

  3. Fragile TOML patching (invoke.go:ensureLoomLocalSources): String-contains checks + append-to-EOF doesn't guarantee the new lines land inside the [tool.uv.sources] section when one already exists elsewhere in the file. Consider using a TOML library or at minimum insert after the existing header line rather than at EOF.

  4. Most training flags are not exposed: Only 4 of ~15 parameters have CLI flags. The rest can't be overridden without editing source. Expose them or document why they're fixed.

  5. ADO clone URL may require auth: defaultLoomRecipeRepo points to msdata.visualstudio.com. Will this work without credentials for users outside the org? If auth is needed, surface a clear error message.

deploy doesn't need init anymore

@jongio jongio left a comment

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 new commit (a95e826) reworks image resolution to derive per-environment image names from the environment name, with --image as an explicit override on both init and deploy. The self-bootstrapping deploy (works without prior init when rle.yaml exists) is a nice UX improvement. The errors.AsType usage and azdext.LocalError error handling are correct and idiomatic.

Three items from my earlier reviews remain unresolved:

  1. scaffold.go:74 strings.ReplaceAll(content, "\n", "\r\n") forces Windows line endings on all platforms. Generated Dockerfiles and Python files will carry \r\n into Linux containers, which can break shebang parsing and cause git diff noise on non-Windows hosts. Remove this line; let files keep native \n endings.

  2. init.go:57 cd %s should use %q to quote paths that may contain spaces (per the repo's path safety convention).

  3. root.go Five command source files (create.go, list.go, show.go, sandbox.go, versions.go) are included in the PR but their constructors are never registered in NewRootCommand. If planned for a follow-up, remove them from this PR to reduce the diff.

Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/scaffold.go Outdated
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/init.go Outdated
jongio
jongio previously requested changes Jun 24, 2026

@jongio jongio left a comment

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.

New commit (f3ab2d2) restores deploy changes lost in the merge conflict. The ACR build integration and image host-qualification helpers work correctly for the described use case.

One new finding: az acr build is called without verifying that az is installed (see inline comment). The invoke command checks for git and uv with exec.LookPath before calling them; the same pattern should apply here.

Three items from earlier reviews remain unresolved:

  1. scaffold.go:74 strings.ReplaceAll(content, "\\n", "\\r\\n") forces CRLF on all platforms. Dockerfiles and Python files with \r\n will break shebang parsing in Linux containers. Remove this line.

  2. init.go:57 cd %s needs %q to quote paths with spaces (AGENTS.md convention).

  3. root.go Five command source files (create.go, list.go, show.go, sandbox.go, versions.go) define constructors never called from NewRootCommand. Wire them in or remove them from this PR.

Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/deploy.go Outdated
@jongio jongio dismissed their stale review June 26, 2026 23:16

Dismissing: this review was incorrectly posted as changes-requested due to an automation bug. The findings remain valid as comments.

@jongio jongio left a comment

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.

Checking in on this PR. My CHANGES_REQUESTED from the previous review cycle is still active. The three core items remain unaddressed, and there's been no author response in the thread.

Still blocking (from prior reviews):

  1. scaffold.go:74 - forces Windows line endings on all generated files unconditionally. Dockerfiles and Python scripts with CRLF will break shebang parsing and cause issues in Linux containers. Remove the strings.ReplaceAll(content, "\\n", "\\r\\n") call.

  2. init.go:57 - the cd path in user-facing output isn't quoted. Paths with spaces will break the suggested command. Use %q instead of %s (explicit repo convention in AGENTS.md).

  3. root.go - five command source files (create.go, list.go, show.go, sandbox.go, versions.go) define constructors that are never registered. The test in root_test.go explicitly asserts they are NOT registered, confirming this is intentional dead code. Remove them from this PR and add them when they are ready to ship.

  4. deploy.go - az acr build is invoked without verifying az is on PATH. The invoke command checks for git and uv before calling them; apply the same pattern here.

Additional item (see inline):

  1. invoke.go (ensureLoomLocalSources) - the TOML patching approach appends lines to EOF rather than inserting under the existing [tool.uv.sources] header. If other TOML sections follow, the appended keys land in the wrong section.

@farhann1 - could you acknowledge these items or let me know if there's a reason they can't be addressed? Happy to discuss tradeoffs.

Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/invoke.go Outdated
@github-actions github-actions Bot mentioned this pull request Jul 2, 2026

@jongio jongio left a comment

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.

Checked the 2 new commits since my last review (cli optimizations + cross-platform path fixes). Clean improvements: dead code removal, better error messages with endpoint visibility, max retry cap on sandbox lease, addEventListener over inline onclick, relative paths in init output, and deploy image naming now includes project prefix to prevent collisions. Tests updated appropriately. Looks good.

@farhann1

farhann1 commented Jul 2, 2026

Copy link
Copy Markdown
Author

@farhann1 please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.

@microsoft-github-policy-service agree [company="{your company}"]

Options:

  • (default - no company specified) I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.
@microsoft-github-policy-service agree
  • (when company given) I am making Submissions in the course of work for my employer (or my employer has intellectual property rights in my Submissions by contract or applicable law). I have permission from my employer to make Submissions and enter into this Agreement on behalf of my employer. By signing below, the defined term “You” includes me and my employer.
@microsoft-github-policy-service agree company="Microsoft"

Contributor License Agreement

@microsoft-github-policy-service agree company="Microsoft"

@jongio jongio left a comment

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.

Incremental review of 1 new commit (e8cfe20 - README update). Editorial improvements only: simplified wording, reorganized .azd-rle.json docs. No code changes. Prior approval stands.

Minor nit: file is missing a trailing newline, but not blocking.

@trangevi trangevi left a comment

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.

Leaving a blocking comment for now, pending review of both the code and broader spec review

@RickWinter RickWinter left a comment

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.

This adds the preview azd ai rle extension: an OpenEnv-style init/run/deploy/invoke flow gated behind AZD_AI_RLE_ENABLE. The overall structure is sound. The command tree follows the extension SDK conventions, path handling in build.go/scaffold.go is careful (Dockerfile paths are validated against the source root, symlinks and .git are skipped on copy), and the sandbox lifecycle in invoke.go is well built. In particular releaseRemoteSandbox deliberately uses a fresh context.Background() with its own timeout, so the deferred release still runs when the user exits the shell with Ctrl-C and the request context is already cancelled. That is the right call and avoids a sandbox leak.

The one item to resolve before merge is in client.go: isLocalControlPlaneEndpoint is defined but never called. With unused enabled in the extension's .golangci.yaml, this should fail the lint gate, which means the "golangci-lint 0 issues" run in the description did not cover this path. It also reads like a dropped guard, since the control plane client sends no auth and RLE_ENDPOINT can point at a remote host. See the inline note for the specifics and the two ways to resolve it.

No other blockers. Given the dead code should break the unused linter, you may prefer to submit this as REQUEST_CHANGES rather than a comment; I have left the draft as COMMENT so you can decide. Everything else can follow as normal preview iteration.

Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/client.go Outdated

@jongio jongio left a comment

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.

New commit (eb14e2d) looks good. UTC time fix in build.ps1 is correct, and the dead code removal in client.go is clean (no orphaned imports). Prior approval stands.

@RickWinter RickWinter left a comment

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.

This adds the preview azd ai rle extension, hidden behind AZD_AI_RLE_ENABLE, for source-first OpenEnv/RLE workflows: init copies a sample into a session folder, run builds and runs it locally in Docker, deploy pushes an image to ACR and creates or updates the environment on the control plane, and invoke leases a remote sandbox and opens an OpenEnv shell plus a local proxy UI. The overall shape is right: it is self-contained under extensions/, the LocalError and path-safety helpers (isSafeRelativePath, isPathWithinRoot) are consistent with the framework, and the command surface is gated correctly.

A few things worth resolving. The init clone pins to the upstream main branch of a third-party repo (huggingface/OpenEnv), so init is non-reproducible and that code is then built into the runtime image and pushed to the user's ACR on deploy; pinning to a tag or commit SHA would remove both the reproducibility gap and the supply-chain surface. Separately, the control-plane client sends no authentication, which is fine for the http://localhost:5000 default but is worth a decision for a remote RLE_ENDPOINT.

Two nits that are correct to leave for a preview: the banner art spells FOUNDRY, and openEnvInvokeFlags carries several fields the invoke command never wires.

None of this blocks a preview surface. The unpinned clone is the one I would address before merge; the rest can follow.

Comment thread cli/azd/extensions/azure.ai.rle/internal/project/scaffold.go
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/client.go
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/banner.go
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/invoke.go Outdated
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/deploy.go
@vhvb1989 vhvb1989 added the skip-governance Skip PR governance checks label Jul 6, 2026

@trangevi trangevi left a comment

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.

Generally I approve the code for a PrPr

Comment thread cli/azd/extensions/azure.ai.rle/internal/project/build.go
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/deploy.go Outdated
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/invoke.go Outdated
Comment thread cli/azd/extensions/azure.ai.rle/internal/cmd/invoke.go Outdated
Comment thread cli/azd/extensions/azure.ai.rle/extension.yaml

@JeffreyCA JeffreyCA 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.

In the future, you can use azd x init --internal to automatically scaffold all the required 1P specific extension files

@jongio jongio left a comment

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.

Incremental review of bab9130 (fix: address review comments).

Flag type split into
emoteInvokeFlags, localRunFlags, and openEnvCallFlags is clean. The new project_endpoint.go module validates and normalizes the Foundry endpoint correctly, with good test coverage for both happy path and error cases. State migration from Project to ProjectEndpoint is consistent across deploy and invoke.

No new issues.

@JeffreyCA

JeffreyCA commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

In terms of general housekeeping we may want to create a separate GitHub label like ext-rle or similar @trangevi

@farhann1 farhann1 requested review from a team and danieljurek as code owners July 7, 2026 20:01

@jongio jongio left a comment

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.

Incremental review of f5798ac (addressing prior feedback). The refactoring looks good: local container lifecycle cleanly separated into run.go, utility code extracted to focused modules (docker.go, runtime.go, identifiers.go), and tests are thorough. CODEOWNERS and CI added. One note: actionlint CI is failing on the new workflow file.

@farhann1 farhann1 requested review from JeffreyCA and RickWinter July 7, 2026 20:25

@JeffreyCA JeffreyCA 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.

Thanks, scaffolding files look good 👍

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

Labels

area/extensions Extensions (general) customer-reported identify a customer issue skip-governance Skip PR governance checks

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants