Contributing schema changes
July 30, 2026 · View on GitHub
Purpose
This guide explains how to make a change to the Radius REST API — for example adding a property to an existing resource or adding a new resource type. The Radius application model and API are defined in TypeSpec under typespec/; the build pipeline compiles that TypeSpec into OpenAPI (Swagger) specs under swagger/ and into Go API client code under pkg/. This is the TypeSpec → Swagger → Go pipeline. Follow it whenever you touch the API surface so the spec, the generated clients, and the Bicep types stay in sync. It is for contributors changing the API; it does not cover resource-provider business logic beyond the generated types.
Prerequisites
- The standard build prerequisites from contributing-code-prerequisites: Go, Node.js, and
pnpm(enabled throughcorepack). The TypeSpec compiler (tsp) and emitters are installed intotypespec/on first use by themake generatetargets, so no global install is needed. - A working clone of the repo where you can run
maketargets.make generateruns thetsptoolchain andgo generate(mocks), so a working Go and Node toolchain is required. - Familiarity with the namespace you are changing. Each API namespace has its own folder under
typespec/(for exampletypespec/Applications.Core,typespec/Radius.Core,typespec/UCP).
Steps
1. Update the TypeSpec definitions
-
Create or update the applicable
.tspfiles (named after the resource type) inside the namespace folder undertypespec/, for exampletypespec/Applications.Core. -
Check the formatting of your TypeSpec:
make tsp-format-checkThis runs
pnpm -C typespec exec tsp format --check "**/*.tsp". To apply the formatter instead of just checking, runpnpm -C typespec exec tsp format "**/*.tsp"from the repo root.
2. Generate the OpenAPI specs and Go clients
Run the umbrella target from the repo root:
make generate
make generate runs the full pipeline: it deletes stale generated code, compiles the resource-provider namespaces' TypeSpec to OpenAPI specs (make generate-openapi-spec — UCP, Applications.Core, Applications.Dapr, Applications.Messaging, Applications.Datastores, and Radius.Core), runs the TypeSpec Go emitter to produce each namespace's Go client, runs go generate ./... (mockgen), generates the Bicep extensibility types, and generates the CRDs. (Not every TypeSpec project emits OpenAPI — for example typespec/GenericResource produces only the generic CLI Go client via make generate-genericcliclient.) The two halves of the pipeline are:
- TypeSpec → Swagger. The
@azure-tools/typespec-autorestemitter writes each API namespace's OpenAPI document toswagger/specification/<service>/resource-manager/<service-name>/<status>/<version>/openapi.json. The output directory is set per namespace by theemitter-output-diroption in that namespace'stspconfig.yaml(for exampletypespec/Applications.Core/tspconfig.yamlemits toswagger/specification/applications). - TypeSpec → Go. The
@azure-tools/typespec-goemitter writes generated client code to a temporary.tsp-go-tmpfolder, which the per-namespacemake generate-rad-<namespace>-clienttargets copy into the matchingpkg/<namespace>/api/<version>/directory and rungo fmtover. Generated files are prefixedzz_generated_.
Alternative: generate a single namespace manually
You normally only need make generate. To regenerate one namespace by hand, run these from the repo root. Generation depends on the tsp toolchain being installed; running make generate once (or make generate-tsp-installed) installs it.
-
Compile the OpenAPI spec for one namespace:
cd typespec/Applications.Core && pnpm exec tsp compile . -
Generate the Go client for that namespace with the TypeSpec Go emitter:
cd typespec/Applications.Core && pnpm exec tsp compile . --emit=@azure-tools/typespec-goThe emitter configuration lives in each namespace's
tspconfig.yaml(under the@azure-tools/typespec-gooptions block). The generated files land in.tsp-go-tmpand must be copied into the matchingpkg/<namespace>/api/<version>/directory; the per-namespacemake generate-rad-<namespace>-clienttargets (for examplemake generate-rad-corerp-client) automate that copy-and-format step, so prefer them over copying by hand.
3. Wire up and test the change
- Add any changes to the Radius resource provider needed to support the new or updated types.
- Add or update tests as needed.
- Open a pull request in the Radius repo. (See the local-testing and merge-order steps below before you expect all checks to pass.)
4. (Optional) Test the schema change locally with Bicep
To confirm your schema compiles in a Bicep template, publish the generated Bicep types to a local target and point bicepconfig.json at them.
-
Install the Bicep CLI. If you already have the Radius CLI installed, you can use the Bicep binary it downloads to
~/.rad/bin/bicepinstead. -
Generate the Bicep types (already done if you ran
make generate):make generate-bicep-typesThis writes the type files under
hack/bicep-types-radius/generated/and rebuilds the unified index athack/bicep-types-radius/generated/index.json. It also writes one reference doc per resource type to<namespace>/<apiVersion>/docs/, for both the TypeSpec-generated and the manifest-generated (contrib) namespaces. Those docs are build artifacts, not checked in, and are published to the docs repo by thepublish-docsworkflow. -
Publish the unified
radiusextension to a target of your choice (a local file path or an OCI registry):make publish-bicep-extension BICEP_PUBLISH_TARGET=<target><target>is either a local path (for example./bin/radius-types.tgz) or an OCI reference (for examplebr:biceptypes.azurecr.io/radius:latest). The target requires thebicepCLI on yourPATH. -
Update the root
bicepconfig.jsonto reference your published extension:{ "extensions": { "radius": "<target>", "aws": "br:biceptypes.azurecr.io/aws:latest" } }Once Bicep restores the new extension, your schema changes are available in Bicep templates.
5. Update docs and samples, then merge in order
- Open PRs in the docs and samples repositories with the corresponding resource changes. Some checks fail until the PRs below start merging.
- Merge in this order once all three PRs (radius, docs, samples) are ready and approved:
- Samples — because of a cyclic dependency between samples and radius (the "Test Quickstarts" task in the samples pipeline runs against the
mainbranch of radius, which does not yet contain your changes), a repo admin must force-merge the samples PR. - Radius — after the samples PR merges, re-run the radius PR checks and merge.
- Docs — re-run any failed checks and merge the docs PR with the updated Bicep files.
- Samples — because of a cyclic dependency between samples and radius (the "Test Quickstarts" task in the samples pipeline runs against the
Verification
-
make tsp-format-checkreportsOKwith no formatting diffs. -
After
make generate, the regenerated OpenAPI spec for your namespace underswagger/specification/.../openapi.jsonreflects your change. -
The regenerated
zz_generated_*.gofiles underpkg/<namespace>/api/<version>/reflect your change. -
The repo still builds and tests pass:
make build make test -
git statusshows the generated spec, client, and Bicep type files changed alongside your.tspedits — generated output must be committed, not left out of the PR.
Troubleshooting
tsporpnpmnot found.make generateinstalls the TypeSpec toolchain intotypespec/viacorepack. Ensure Node.js is installed and on yourPATH, then re-runmake generate(ormake generate-tsp-installed). See contributing-code-prerequisites.make tsp-format-checkfails. Runpnpm -C typespec exec tsp format "**/*.tsp"to apply the formatter, then re-run the check.- Generated files keep reappearing as changes. Generated
zz_generated_*.goandopenapi.jsonfiles are committed artifacts. Runmake generate, then commit the regenerated output so it matches your TypeSpec. make publish-bicep-extensionerrors that the index does not exist. Runmake generate-bicep-typesfirst; the target publisheshack/bicep-types-radius/generated/index.json, which that command creates.make publish-bicep-extensioncannot findbicep. Install the Bicep CLI and ensure it is on yourPATH, or use the binary at~/.rad/bin/bicepfrom a Radius CLI install.Reference-doc generator not found. The contrib namespaces render their reference docs with the compiled TypeSpec emitter. Runmake generate-bicep-types-emitterto build it, then re-runmake generate-bicep-types-contrib.