Skip to content

Feature spec: Dynamic Bicep Extensions Served by the Radius Control Plane#11907

Open
zachcasper wants to merge 4 commits into
radius-project:mainfrom
zachcasper:bicep-extension-refactor
Open

Feature spec: Dynamic Bicep Extensions Served by the Radius Control Plane#11907
zachcasper wants to merge 4 commits into
radius-project:mainfrom
zachcasper:bicep-extension-refactor

Conversation

@zachcasper
Copy link
Copy Markdown
Contributor

Description

Add a design document proposing that the Radius control plane become the single source of truth for Bicep extensions, replacing the current dual-pipeline model (release-time ACR publishes + manual rad bicep publish-extension).

Under the proposal:

  • A new control-plane API returns a Bicep extension artifact computed on demand from the currently-registered resource types. No new Ingress, OCI registry, DNS, or TLS provisioning is required to expose it; it reuses the auth path rad already uses.
  • A new rad resource-type update CLI command fetches that artifact and writes it to ~/.rad/bicep-extension.tgz. rad deploy and rad run refresh it as a side effect, closing the staleness window in the normal authoring → deploy loop.
  • rad init becomes kubecontext-aware: it installs Radius if the current kubecontext has none, otherwise skips the install step. In both cases it writes ~/.rad/bicep-extension.tgz and creates or merges ~/bicepconfig.json with a single extensions.radius entry pointing at that file. Bicep's existing parent-directory bicepconfig.json resolution covers every .bicep file under $HOME automatically.
  • The four split radius* aliases (radius, radiusCompute, radiusData, radiusSecurity) are consolidated into a single radius alias; legacy entries in an existing ~/bicepconfig.json are removed by rad init as an intentional forcing function.
  • rad bicep publish-extension is removed from the CLI. Previously-published artifacts on biceptypes.azurecr.io remain readable for users on older rad versions.

The document records the four other delivery models that were evaluated (long-running proxy daemon, Ingress + anonymous OCI endpoint, Kubernetes aggregation layer, and control-plane-pushes-to-customer-registry) and why each was rejected for v1.

No code changes; design document only.

Type of change

  • This pull request is a design document and only includes files in the eng/design-notes directory.

Fixes: #TBD

Contributor checklist

  • An overview of proposed schema changes is included in a linked GitHub issue.
    • Not applicable
  • A design document is added or updated under eng/design-notes/ in this repository, if new APIs are being introduced.
    • Yes
  • The design document has been reviewed and approved by Radius maintainers/approvers.
    • Yes
    • Not applicable (pending review on this PR)
  • A PR for resource-types-contrib is created, if resource types or recipes are affected by the changes in this PR.
    • Not applicable
  • A PR for dashboard is created, if the Radius Dashboard is affected by the changes in this PR.
    • Not applicable
  • A PR for the documentation repository is created, if the changes in this PR affect the documentation or any user facing updates are made.
    • Not applicable (follow-up docs PR required when implementation lands)

Signed-off-by: Zach Casper <zachcasper@microsoft.com>
Signed-off-by: Zach Casper <zachcasper@microsoft.com>
Copilot AI review requested due to automatic review settings May 15, 2026 04:05
@zachcasper zachcasper requested review from a team as code owners May 15, 2026 04:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 design note proposing a shift from release-time/manual publishing of Radius Bicep extensions to a control-plane-served, on-demand extension artifact that the rad CLI downloads to a workstation-global .tgz and references via a single radius alias.

Changes:

  • Introduces a proposed control-plane API that generates a Bicep extension artifact from the currently registered resource types.
  • Proposes new/updated CLI behaviors (rad resource-type update, kubecontext-aware rad init, and implicit refresh during rad deploy/rad run) to keep the local extension current.
  • Proposes consolidating the four radius* aliases into a single radius alias and removing rad bicep publish-extension.

Comment thread eng/design-notes/bicep/2026-05-dynamic-bicep-extensions.md
Comment thread eng/design-notes/bicep/2026-05-dynamic-bicep-extensions.md Outdated
Comment thread eng/design-notes/bicep/2026-05-dynamic-bicep-extensions.md Outdated
Signed-off-by: Zach Casper <zachcasper@microsoft.com>

Developer (steady state, type set changes server-side):

1. Run `rad resource-type update` to refresh now, or just run the next `rad deploy` / `rad run`, which refresh `~/.rad/bicep-extension.tgz` as a side effect.
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.

I like the idea of having a separate command that imports the server-side type library to developer workstations, but I think it should be separate from the rad resource-type CRUDL command.

rad resource-type update implies that the developer is updating the type schema on the server. In an enterprise setup, platform engineers would typically use RBAC to restrict who can create or update resource type definitions.

I think it would be better to call this something like rad extension update or rad extension import implying what the command is actually doing - pulling the extension from the Radius control plane and updating the local extension configuration on the developer machine.

It also maps to the existing extension radius experience in application definition, so the mental model stays the same .

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, I debated many options here. I'm open to suggestions. Here is what was considered:

rad resource-type update — command-naming debate

Options considered

# Candidate Pros Cons
1 rad bicep extension sync (original) Most precise; explicitly names artifact + namespace. Verbose. Only makes sense if more rad bicep extension <verb> siblings (show, path) are likely.
2 rad bicep sync Shorter; discoverable next to other rad bicep … commands. Still ties the verb to the artifact format. Hides that the catalog (not the file) is the real input.
3 rad sync Reads cleanly; leaves room for future syncs. Vague; future-proofing was speculative (YAGNI). No concrete second target identified.
4 rad resource-type sync Names what is synced (the catalog), not the file format. Mirrors rad resource-type create. Leaves room for non-Bicep outputs (Terraform schema, LSP index) without renaming. sync has weak prior art for schema/catalog caches — the ecosystem (helm repo update, apt update, brew update, terraform init -upgrade) overwhelmingly uses update.
5 rad resource-type refresh Semantically precise; no collision. Less familiar verb than sync or update in modern CLIs.
6 rad extension update Short; uses the established update verb. "extension" collides hard with Bicep's own vocabulary (extension keyword, extensions block in bicepconfig.json, "extension types"); ambiguous with a future rad plugin system. Names a file artifact rather than the catalog.
7 rad resource-type update (selected) Names the catalog, not the artifact. Mirrors rad resource-type create (symmetric: platform engineer creates server-side, developer updates client-side). Uses update — the established verb in this ecosystem for "pull fresh catalog from server." Singular form matches existing CLI conventions. Preserves optionality for future outputs (Terraform, LSP) under the same noun. Verb collides loosely with the idea of "modify a resource type" — mitigated because schema edits happen via rad resource-type create -f manifest.yaml in practice, not via an update subcommand.

Why option 7 won

  1. Catalog, not artifact. The thing being kept fresh is the resource-type catalog. The .tgz is one current serialization; in the future the same command can emit other formats.
  2. Symmetric with rad resource-type create. Platform engineer creates types; developer updates the local mirror. Same noun on both sides.
  3. update is the dominant verb in the ecosystem. helm repo update, apt update, brew update, terraform init -upgrade. sync is mostly used for filesystem mirrors (rclone sync, aws s3 sync) and fork-to-upstream (gh repo sync), neither of which matches our shape.
  4. Avoids the overloaded word "extension." Reserves that term for Bicep's own meaning and for a future rad plugin namespace.
  5. Lets rad init absorb the first-run case. Because rad init became kubecontext-aware in the same change, rad resource-type update is only needed for explicit refresh — the everyday developer never has to type it, which lowers the cost of choosing a slightly longer name.


## Key dependencies and risks

* **Dependency – Bicep CLI local-file extension references and parent-directory `bicepconfig.json` resolution.** The integration point is Bicep's existing support for a local-file `extensions` entry plus its existing parent-walk to find `bicepconfig.json`. Bicep's walk reaches `$HOME` for any `.bicep` source under `$HOME`, but does not search `~/.bicep/` or XDG paths. No change to the upstream Bicep CLI or Bicep VS Code extension is required. Risk: if Bicep changes its parent-walk semantics, every workstation breaks. Mitigation: this is documented Bicep behavior; pin Bicep version testing in CI.
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.

As I understand here - bicepconfig.json will still be maintained at the repo level and the extensions in .rad/ will be refreshed by rad init or an explicit command to update extensions locally. We maintain the bicepconfig.json outside of .rad/ because of Bicep's config resolution?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No, rad init will now write bicepconfig.json in the users' home directory. The contents will be:

{
  "extensions": {
    "radius": ".rad/bicep-extension.tgz"
  }
}

The downloaded Bicep extension will be ~/.rad/bicep-extension.tgz.

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.

Oh I was thinking about this from Repo Radius perspective. How this would be created and maintained for repositories with radius installed? May be some clarity around that would help.

* **Dependency – Authentication path `rad` already uses for control-plane calls.** The new extension API reuses the same auth. The Bicep CLI itself never authenticates to the control plane (it only sees the local file).
* **Risk – Stale `~/.rad/bicep-extension.tgz` on a workstation that has not run `rad` since the control plane changed.** Mitigated by routine `rad` commands (`deploy`, `run`) refreshing as a side-effect and by `rad resource-type update` being a single command.
* **Risk – `.bicep` files outside `$HOME` are not covered automatically.** Mitigated by documentation; advanced users place a `bicepconfig.json` somewhere in their source tree by hand.
* **Risk – Devcontainer / Codespaces / remote-SSH workspaces have a different `$HOME`.** `rad init` must be re-run inside the container; the artifact is per-environment. Documented limitation.
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.

Would this be a risk if bicepconfig.json is maintained at per repo level ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

If a is running in a dev container (or another workstation for that matter), they will not have the Bicep extension in their environment. This is obvious and a somewhat silly risk to be documented.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants