Skip to content

feat: ai rle v1#8782

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

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

Conversation

@farhann1

Copy link
Copy Markdown

No description provided.

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.

@microsoft-github-policy-service

Copy link
Copy Markdown
Contributor

@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

Contribution License Agreement

This Contribution License Agreement (“Agreement”) is agreed to by the party signing below (“You”),
and conveys certain license rights to Microsoft Corporation and its affiliates (“Microsoft”) for Your
contributions to Microsoft open source projects. This Agreement is effective as of the latest signature
date below.

  1. Definitions.
    “Code” means the computer software code, whether in human-readable or machine-executable form,
    that is delivered by You to Microsoft under this Agreement.
    “Project” means any of the projects owned or managed by Microsoft and offered under a license
    approved by the Open Source Initiative (www.opensource.org).
    “Submit” is the act of uploading, submitting, transmitting, or distributing code or other content to any
    Project, including but not limited to communication on electronic mailing lists, source code control
    systems, and issue tracking systems that are managed by, or on behalf of, the Project for the purpose of
    discussing and improving that Project, but excluding communication that is conspicuously marked or
    otherwise designated in writing by You as “Not a Submission.”
    “Submission” means the Code and any other copyrightable material Submitted by You, including any
    associated comments and documentation.
  2. Your Submission. You must agree to the terms of this Agreement before making a Submission to any
    Project. This Agreement covers any and all Submissions that You, now or in the future (except as
    described in Section 4 below), Submit to any Project.
  3. Originality of Work. You represent that each of Your Submissions is entirely Your original work.
    Should You wish to Submit materials that are not Your original work, You may Submit them separately
    to the Project if You (a) retain all copyright and license information that was in the materials as You
    received them, (b) in the description accompanying Your Submission, include the phrase “Submission
    containing materials of a third party:” followed by the names of the third party and any licenses or other
    restrictions of which You are aware, and (c) follow any other instructions in the Project’s written
    guidelines concerning Submissions.
  4. Your Employer. References to “employer” in this Agreement include Your employer or anyone else
    for whom You are acting in making Your Submission, e.g. as a contractor, vendor, or agent. If Your
    Submission is made in the course of Your work for an employer or Your employer has intellectual
    property rights in Your Submission by contract or applicable law, You must secure permission from Your
    employer to make the Submission before signing this Agreement. In that case, the term “You” in this
    Agreement will refer to You and the employer collectively. If You change employers in the future and
    desire to Submit additional Submissions for the new employer, then You agree to sign a new Agreement
    and secure permission from the new employer before Submitting those Submissions.
  5. Licenses.
  • Copyright License. You grant Microsoft, and those who receive the Submission directly or
    indirectly from Microsoft, a perpetual, worldwide, non-exclusive, royalty-free, irrevocable license in the
    Submission to reproduce, prepare derivative works of, publicly display, publicly perform, and distribute
    the Submission and such derivative works, and to sublicense any or all of the foregoing rights to third
    parties.
  • Patent License. You grant Microsoft, and those who receive the Submission directly or
    indirectly from Microsoft, a perpetual, worldwide, non-exclusive, royalty-free, irrevocable license under
    Your patent claims that are necessarily infringed by the Submission or the combination of the
    Submission with the Project to which it was Submitted to make, have made, use, offer to sell, sell and
    import or otherwise dispose of the Submission alone or with the Project.
  • Other Rights Reserved. Each party reserves all rights not expressly granted in this Agreement.
    No additional licenses or rights whatsoever (including, without limitation, any implied licenses) are
    granted by implication, exhaustion, estoppel or otherwise.
  1. Representations and Warranties. You represent that You are legally entitled to grant the above
    licenses. You represent that each of Your Submissions is entirely Your original work (except as You may
    have disclosed under Section 3). You represent that You have secured permission from Your employer to
    make the Submission in cases where Your Submission is made in the course of Your work for Your
    employer or Your employer has intellectual property rights in Your Submission by contract or applicable
    law. If You are signing this Agreement on behalf of Your employer, You represent and warrant that You
    have the necessary authority to bind the listed employer to the obligations contained in this Agreement.
    You are not expected to provide support for Your Submission, unless You choose to do so. UNLESS
    REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, AND EXCEPT FOR THE WARRANTIES
    EXPRESSLY STATED IN SECTIONS 3, 4, AND 6, THE SUBMISSION PROVIDED UNDER THIS AGREEMENT IS
    PROVIDED WITHOUT WARRANTY OF ANY KIND, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY OF
    NONINFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
  2. Notice to Microsoft. You agree to notify Microsoft in writing of any facts or circumstances of which
    You later become aware that would make Your representations in this Agreement inaccurate in any
    respect.
  3. Information about Submissions. You agree that contributions to Projects and information about
    contributions may be maintained indefinitely and disclosed publicly, including Your name and other
    information that You submit with Your Submission.
  4. Governing Law/Jurisdiction. This Agreement is governed by the laws of the State of Washington, and
    the parties consent to exclusive jurisdiction and venue in the federal courts sitting in King County,
    Washington, unless no federal subject matter jurisdiction exists, in which case the parties consent to
    exclusive jurisdiction and venue in the Superior Court of King County, Washington. The parties waive all
    defenses of lack of personal jurisdiction and forum non-conveniens.
  5. Entire Agreement/Assignment. This Agreement is the entire agreement between the parties, and
    supersedes any and all prior agreements, understandings or communications, written or oral, between
    the parties relating to the subject matter hereof. This Agreement may be assigned by Microsoft.

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.

Write-Host "Error: Failed to get git commit hash"
exit 1
}
$BUILD_DATE = (Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ")

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

rootCmd.AddCommand(newMetadataCommand(rootCmd))

return rootCmd
}

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.

Five command constructors (newCreateCommand, newListCommand, newShowCommand, newSandboxCommand, newVersionsCommand) are defined in this package but never called. If they're planned for a follow-up PR, consider removing them from this PR to keep the diff focused. If they should be available now, wire them in here.

content = strings.ReplaceAll(content, token, value)
}
content = strings.ReplaceAll(content, "\n", "\r\n")
fullPath := filepath.Join(sessionDir, filepath.FromSlash(relativePath))

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 forces Windows line endings on all platforms. Generated Dockerfiles and Python files will have \r\n on Linux/macOS, which can cause container build failures (e.g., shebang parsing) and git noise.

Remove this line entirely. Let files keep their native \n endings. Git handles CRLF conversion on Windows if .gitattributes is configured.

_, err = fmt.Fprintf(
cmd.OutOrStdout(),
"Created OpenEnv-style environment at: %s\nNext steps:\n cd %s\n azd ai rle deploy\n",
displayDir,

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.

Paths with spaces will break the suggested cd command. This repo requires quoting user-facing paths (AGENTS.md convention). Use %q instead of %s for the cd target.

if body != nil {
req.Header.Set("Content-Type", "application/json")
}
if token := os.Getenv("RLE_BEARER_TOKEN"); token != "" {

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.

Consider logging a warning (to stderr) when sending a bearer token over a non-TLS, non-localhost endpoint. Silent credential leakage over HTTP to a remote host is a security concern.

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

}

// normalizeRegistryLoginServer turns a registry short name ("devrle") into a login server
// ("devrle.azurecr.io"). A value that already contains a '.' is assumed to be a login server.

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.

These pure helper functions (splitImageHost, normalizeRegistryLoginServer, registryShortName, fileExists) plus isNotFoundError in client.go are great candidates for table-driven unit tests. They have clear input/output contracts and no side effects (except fileExists). Consider adding coverage in a follow-up, especially for edge cases like an image with no tag, an empty registry string, or a login server without a dot.

registry string
skipBuild bool
}{}

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.

[nit] The default registry value 'devrle' is clearly a dev-team convenience. That is fine for now, but document it in the --registry help string or README so users outside the team know they need to override it.

return &azdext.LocalError{
Message: fmt.Sprintf("Failed to build and push image '%s' to registry '%s': %v", repoTag, registryName, err),
Code: "rle_acr_build_failed",
Category: azdext.LocalErrorCategoryUser,

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 404-fallback-to-create is a nice UX touch. One consideration: if state.Project was accidentally changed (or the state file was corrupted), this silently creates a new environment rather than surfacing the mismatch. The printed message helps, but you might want to log the old environment ID in the output so users can spot unintentional recreation.

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

for token, value := range replacements {
content = strings.ReplaceAll(content, token, value)
}
content = strings.ReplaceAll(content, "\n", "\r\n")

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.

Still present from prior review: this forces \r\n on every generated file regardless of host OS. Dockerfiles and Python scripts with \r bytes can break shebang parsing and cause exec format error inside Linux containers. Remove this line entirely.

}
_, err = fmt.Fprintf(
cmd.OutOrStdout(),
"Created OpenEnv-style environment at: %s\nNext steps:\n cd %s\n azd ai rle deploy\n",

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.

Still present from prior review: the cd path isn't quoted. A path with spaces (e.g. C:\Users\My Name\code_rl) will break the suggested command. Use %q instead of %s for the cd target.

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

repoTag, registryName); err != nil {
return err
}
build := exec.CommandContext(cmd.Context(),

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.

Add exec.LookPath("az") before this block, matching the git and uv checks in invoke.go. Without it, a missing Azure CLI produces an error about "push access to the registry" when the real problem is that az isn't on PATH.

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

Labels

customer-reported identify a customer issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants