Skip to content

Remove the need to add radius properties into every RRT schema explicitly#12252

Merged
nithyatsu merged 16 commits into
radius-project:mainfrom
nithyatsu:impl-base-manifest
Jun 30, 2026
Merged

Remove the need to add radius properties into every RRT schema explicitly#12252
nithyatsu merged 16 commits into
radius-project:mainfrom
nithyatsu:impl-base-manifest

Conversation

@nithyatsu

@nithyatsu nithyatsu commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Description

This pull request introduces a new mechanism for merging common "base resource" properties into all resource type schemas in the bicep-tools converter, ensuring consistency with server-side validation and reducing duplication. The main changes include implementing a reusable merger for base properties, updating the converter to apply this merger automatically, and removing redundant property declarations from manifest files. Comprehensive tests and documentation updates support these changes.

To test these changes:

Manual test: base-manifest feature

Setup

mkdir -p /tmp/base-test && cd /tmp/base-test


### Happy path

1. Create `widgets.yaml` (no base properties declared):

```yaml
namespace: Demo.Examples
types:
  widgets:
    apiVersions:
      "2026-06-01-preview":
        schema:
          type: object
          properties:
            size:
              type: integer
              description: Widget size.
            color:
              type: string
              description: Widget color.
          required:
            - size
            - environment        # allowed: re-asserting a base property
     capabilities: ["ManualResourceProvisioning"]
  1. Register the type and confirm base props were merged:
rad resource-type create -f widgets.yaml
rad resource-type show Demo.Examples/widgets -o json 

Expect: "application","codeReference","color","connections","environment","size" defined as expected

3. Generate the Bicep extension and confirm base props were merged:

```sh
rad bicep publish-extension --from-file widgets.yaml --target ./demo-examples.tgz --force


4. Create `bicepconfig.json`:

```json
{
  "experimentalFeaturesEnabled": { "extensibility": true },
  "extensions": {
    "radius": "br:biceptypes.azurecr.io/radius:latest",
    "demo": "./demo-examples.tgz"
  }
}
  1. Create widget-app.bicep:
extension radius
extension demo

@description('Existing Radius environment.')
param environment string

@description('Optional Radius application.')
param application string = ''

resource w 'Demo.Examples/widgets@2026-06-01-preview' = {
  name: 'demo-widget'
  properties: {
    environment: environment
    application: application
    connections: {}
    codeReference: 'https://github.com/myorg/repo/blob/abc1234/widgets.cpp#L1' # 
    size: 10
    color: 'red'
  }
}
  1. Deploy and verify:
rad deploy widget-app.bicep \
  --parameters environment=$(rad env show -o json | jq -r .id) \
  --parameters application=$(rad app show <your-app> -o json | jq -r .id)

rad resource list Demo.Examples/widgets

Expect: Bicep compiles, deploy succeeds, resource appears with all four base props.

Error path — Bicep omits the required environment/ other auto-injected properties

Create widget-missing-env.bicep:

extension radius
extension demo

resource w 'Demo.Examples/widgets@2026-06-01-preview' = {
  name: 'demo-widget-missing-env'
  properties: {
    // environment intentionally omitted — base marks it required.
    size: 5
    color: 'blue'
  }
}

Type of change

  • This pull request fixes a bug in Radius and has an approved issue (issue link required).
  • This pull request adds or changes features of Radius and has an approved issue (issue link required).
  • This pull request is a minor refactor, code cleanup, test improvement, or other maintenance task and doesn't change the functionality of Radius (issue link optional).
  • This pull request is a design document and only includes files in the eng/design-notes directory.

Fixes: #issue_number

Contributor checklist

Please verify that the PR meets the following requirements, where applicable:

  • An overview of proposed schema changes is included in a linked GitHub issue.
    • Yes
    • Not applicable
  • A design document is added or updated under eng/design-notes/ in this repository, if new APIs are being introduced.
    • Yes
    • Not applicable
  • The design document has been reviewed and approved by Radius maintainers/approvers.
    • Yes
    • Not applicable
  • A PR for resource-types-contrib is created, if resource types or recipes are affected by the changes in this PR.
    • Yes
    • Not applicable
  • A PR for dashboard is created, if the Radius Dashboard is affected by the changes in this PR.
    • Yes
    • 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.
    • Yes
    • Not applicable

@codecov

codecov Bot commented Jun 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 81.02190% with 26 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.99%. Comparing base (f406958) to head (95a7820).

Files with missing lines Patch % Lines
pkg/schema/baseresource/loader.go 81.65% 14 Missing and 6 partials ⚠️
pkg/cli/manifest/validation.go 73.33% 2 Missing and 2 partials ⚠️
pkg/cli/manifest/registermanifest.go 0.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #12252      +/-   ##
==========================================
+ Coverage   52.92%   52.99%   +0.06%     
==========================================
  Files         753      754       +1     
  Lines       48468    48604     +136     
==========================================
+ Hits        25654    25759     +105     
- Misses      20401    20420      +19     
- Partials     2413     2425      +12     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

This PR introduces a canonical “base resource manifest” that defines Radius-owned, common schema properties (notably application, environment, connections, and the new codeReference) and ensures they are automatically merged into every resource type schema during manifest validation/registration and during Bicep type generation. It also updates test and built-in provider manifests to omit these common properties (relying on the merge) while adding validation to prevent per-type schemas from redeclaring the reserved base properties.

Changes:

  • Added pkg/schema/baseresource with an embedded base.yaml plus a loader/merger to inject base properties + required fields into decoded schemas.
  • Updated CLI manifest validation (ValidateManifest) to apply the base manifest (and reject redeclaration conflicts) before schema validation/registration.
  • Updated schema validation + utilities to recognize codeReference, and updated manifests/testdata + bicep-tools conversion to rely on the merged base properties.

Reviewed changes

Copilot reviewed 31 out of 31 changed files in this pull request and generated no comments.

Show a summary per file
File Description
test/functional-portable/dynamicrp/noncloud/resources/testdata/testresourcetypes.yaml Removes explicit base properties from dynamic-rp test resource schemas so tests rely on base-manifest merging.
pkg/ucp/integrationtests/resourceproviders/testdata/manifests-no-location/persistentVolumes.yaml Simplifies schema to properties: {} while retaining required list; relies on base-manifest merge during initializer validation.
pkg/ucp/integrationtests/resourceproviders/testdata/manifests-no-location/containers.yaml Same as above for containers no-location startup registration coverage.
pkg/schema/validator.go Adds codeReference to reserved-property type constraints (string-only).
pkg/schema/validator_test.go Adds unit coverage for codeReference reserved-property type validation.
pkg/schema/baseresource/loader.go New base-manifest loader + merger (Load/MustLoad/Apply) and conflict detection helpers.
pkg/schema/baseresource/loader_test.go Unit tests for base-manifest parsing, merging behavior, idempotency, and copy-safety.
pkg/schema/baseresource/base.yaml New canonical YAML definition of base properties + required set (embedded via go:embed).
pkg/resourceutil/utils.go Treats codeReference as a framework-owned/basic property for filtering/processing.
pkg/dynamicrp/datamodel/dynamicresource.go Adds a CodeReference() accessor on the dynamic resource adapter to read the base property.
pkg/dynamicrp/datamodel/dynamicresource_test.go Adds tests for CodeReference() behavior across missing/invalid/valid cases.
pkg/cli/manifest/validation.go Loads a single base manifest at init and adds applyBaseResourceManifest() to merge + enforce no-redeclare.
pkg/cli/manifest/validation_test.go Adds tests ensuring merge behavior and redeclare rejection in the CLI manifest pipeline.
pkg/cli/manifest/testdata/merge-base-manifest.yaml New manifest fixture used to validate end-to-end base-merge behavior in ValidateManifest.
pkg/cli/manifest/registermanifest.go Calls applyBaseResourceManifest() inside ValidateManifest before schema validation/registration.
pkg/cli/manifest/registermanifest_test.go Adds a regression test proving ValidateManifest returns schemas already merged with base properties.
pkg/cli/cmd/resourcetype/create/testdata/valid.yaml Updates resourcetype-create test manifests to omit base properties from schemas.
eng/design-notes/resources/2026-06-base-resource-manifest.md Updates design note to reflect immutable BaseManifest load-once model + merge chokepoint behavior.
deploy/manifest/built-in-providers/self-hosted/secrets.yaml Removes explicit base properties from built-in schema; keeps required semantics; formatting cleanup.
deploy/manifest/built-in-providers/self-hosted/routes.yaml Same as above; removes explicit base properties and normalizes formatting.
deploy/manifest/built-in-providers/self-hosted/persistentVolumes.yaml Same as above; removes explicit base properties and normalizes formatting.
deploy/manifest/built-in-providers/self-hosted/mySqlDatabases.yaml Removes explicit base properties and normalizes formatting in schema/docs blocks.
deploy/manifest/built-in-providers/self-hosted/containers.yaml Removes explicit base properties (including connections) and normalizes formatting.
deploy/manifest/built-in-providers/dev/secrets.yaml Mirrors self-hosted manifest updates for dev manifests.
deploy/manifest/built-in-providers/dev/routes.yaml Mirrors self-hosted manifest updates for dev manifests.
deploy/manifest/built-in-providers/dev/persistentVolumes.yaml Mirrors self-hosted manifest updates for dev manifests.
deploy/manifest/built-in-providers/dev/mySqlDatabases.yaml Mirrors self-hosted manifest updates for dev manifests.
deploy/manifest/built-in-providers/dev/containers.yaml Mirrors self-hosted manifest updates for dev manifests.
bicep-tools/pkg/converter/converter.go Applies base-property merge before emitting Bicep property types, matching server-side behavior.
bicep-tools/pkg/converter/baseresource.go New bicep-tools base-manifest decode-from-canonical-YAML + merge helper.
bicep-tools/pkg/converter/baseresource_test.go Unit tests ensuring canonical YAML decode and merge semantics in bicep-tools.

nithyatsu added 15 commits June 26, 2026 16:32
Wire baseresource.Apply into pkg/cli/manifest so every registration path
(rad resource-type create, RegisterFile/RegisterDirectory, and the UCP
initializer service at startup) merges the common base properties into
per-type schemas before validation and registration. The base manifest is
loaded once at package init and reused, immutable, for the process lifetime.

Add codeReference to the validator's reserved string-shape check so a
type-declared codeReference must be a string, mirroring application and
environment.

Signed-off-by: Nithya Subramanian <nithyasu@microsoft.com>
Add codeReference to resourceutil.BasicProperties so the runtime treats it
as a framework-owned property (excluded from connection environment variables
and from user-supplied resource properties), and add a CodeReference() accessor
on the dynamic-rp basic-properties adapter mirroring ApplicationID and
EnvironmentID.

Signed-off-by: Nithya Subramanian <nithyasu@microsoft.com>
Add a parallel base-resource merger to bicep-tools so the published Bicep
types expose application, environment, connections, and codeReference even
when an author omits them, mirroring the server-side merge in pkg/cli/manifest.

bicep-tools models schemas with its own typed manifest.Schema rather than the
map[string]any the schema package merges, so the base set is duplicated as a
typed literal. A sync test reads the canonical pkg/schema/baseresource/base.yaml
and fails CI if the literal drifts. manifest.Schema is unchanged.

Signed-off-by: Nithya Subramanian <nithyasu@microsoft.com>
Now that the base resource manifest injects application, environment,
connections, and codeReference into every schema, the dynamic-rp functional
test resource types no longer need to restate them. Remove the duplicated
property declarations and the application/environment required entries
(environment stays required via the base merge), keeping only type-specific
properties and required fields.

Signed-off-by: Nithya Subramanian <nithyasu@microsoft.com>
The containers connections schema carries an optional disableDefaultEnvVars
flag that the base connections lacked. Add it to the canonical base.yaml and
the bicep-tools typed mirror so every resource type's connections inherits it
and containers can stop declaring its own connections block.

Signed-off-by: Nithya Subramanian <nithyasu@microsoft.com>
Base property names (application, environment, connections, codeReference)
are reserved by Radius and injected automatically. Reject any per-type schema
that redeclares one under "properties" via a pre-merge ConflictingProperties
check; a base property may still be listed under "required" to make it
mandatory.

Drop the now-redundant declarations from the built-in provider manifests
(self-hosted and dev) and the affected test fixtures, leaving their required
lists intact as allowed references to the base-provided properties.

Signed-off-by: Nithya Subramanian <nithyasu@microsoft.com>
@nithyatsu nithyatsu force-pushed the impl-base-manifest branch from 2e38a70 to 6728365 Compare June 26, 2026 23:33
@nithyatsu nithyatsu marked this pull request as ready for review June 26, 2026 23:45
@nithyatsu nithyatsu requested review from a team as code owners June 26, 2026 23:45
@nithyatsu nithyatsu enabled auto-merge June 26, 2026 23:57
@radius-functional-tests

radius-functional-tests Bot commented Jun 27, 2026

Copy link
Copy Markdown

Radius functional test overview

🔍 Go to test action run

Click here to see the test run details
Name Value
Repository nithyatsu/radius
Commit ref 95a7820
Unique ID funce0ab187964
Image tag pr-funce0ab187964
  • Dapr: 1.14.4
  • Azure KeyVault CSI driver: 1.4.2
  • Azure Workload identity webhook: 1.3.0
  • Bicep recipe location ghcr.io/radius-project/dev/test/testrecipes/test-bicep-recipes/<name>:pr-funce0ab187964
  • Terraform recipe location http://tf-module-server.radius-test-tf-module-server.svc.cluster.local/<name>.zip (in cluster)
  • applications-rp test image location: ghcr.io/radius-project/dev/applications-rp:pr-funce0ab187964
  • dynamic-rp test image location: ghcr.io/radius-project/dev/dynamic-rp:pr-funce0ab187964
  • controller test image location: ghcr.io/radius-project/dev/controller:pr-funce0ab187964
  • ucp test image location: ghcr.io/radius-project/dev/ucpd:pr-funce0ab187964
  • deployment-engine test image location: ghcr.io/radius-project/deployment-engine:latest

Test Status

⌛ Building Radius and pushing container images for functional tests...
✅ Container images build succeeded
⌛ Publishing Bicep Recipes for functional tests...
✅ Recipe publishing succeeded
⌛ Starting ucp-cloud functional tests...
⌛ Starting corerp-cloud functional tests...
✅ ucp-cloud functional tests succeeded
❌ corerp-cloud functional test failed. Please check the logs for more details
⌛ Starting corerp-cloud functional tests...
✅ corerp-cloud functional tests succeeded

@github-actions

github-actions Bot commented Jun 27, 2026

Copy link
Copy Markdown

Functional Tests - corerp-cloud

26 tests  ±0   25 ✅ ±0   10m 52s ⏱️ -14s
 2 suites ±0    1 💤 ±0 
 1 files   ±0    0 ❌ ±0 

Results for commit 95a7820. ± Comparison against base commit f406958.

♻️ This comment has been updated with latest results.

@brooke-hamilton brooke-hamilton linked an issue Jun 30, 2026 that may be closed by this pull request
@nithyatsu nithyatsu added this pull request to the merge queue Jun 30, 2026
Merged via the queue into radius-project:main with commit bf1015c Jun 30, 2026
72 of 73 checks passed
@nithyatsu nithyatsu deleted the impl-base-manifest branch June 30, 2026 19:38
@nithyatsu nithyatsu changed the title Impl base manifest Remove the need to add radius properties into every RRT schema explicitly Jun 30, 2026
sk593 pushed a commit that referenced this pull request Jul 6, 2026
# Description

This pull request introduces a new mechanism for merging common "base
resource" properties into all resource type schemas in the `bicep-tools`
converter, ensuring consistency with server-side validation and reducing
duplication. The main changes include implementing a reusable merger for
base properties, updating the converter to apply this merger
automatically, and removing redundant property declarations from
manifest files. Comprehensive tests and documentation updates support
these changes.

To test these changes:

## Manual test: base-manifest feature

### Setup

mkdir -p /tmp/base-test && cd /tmp/base-test
```

### Happy path

1. Create `widgets.yaml` (no base properties declared):

```yaml
namespace: Demo.Examples
types:
  widgets:
    apiVersions:
      "2026-06-01-preview":
        schema:
          type: object
          properties:
            size:
              type: integer
              description: Widget size.
            color:
              type: string
              description: Widget color.
          required:
            - size
            - environment        # allowed: re-asserting a base property
     capabilities: ["ManualResourceProvisioning"]
```

2. Register the type and confirm base props were merged:

```sh
rad resource-type create -f widgets.yaml
rad resource-type show Demo.Examples/widgets -o json

Expect:
"application","codeReference","color","connections","environment","size"
defined as expected

3. Generate the Bicep extension and confirm base props were merged:

```sh
rad bicep publish-extension --from-file widgets.yaml --target ./demo-examples.tgz --force

4. Create `bicepconfig.json`:

```json
{
  "experimentalFeaturesEnabled": { "extensibility": true },
  "extensions": {
    "radius": "br:biceptypes.azurecr.io/radius:latest",
    "demo": "./demo-examples.tgz"
  }
}
```

5. Create `widget-app.bicep`:

```bicep
extension radius
extension demo

@description('Existing Radius environment.')
param environment string

@description('Optional Radius application.')
param application string = ''

resource w 'Demo.Examples/widgets@2026-06-01-preview' = {
  name: 'demo-widget'
  properties: {
    environment: environment
    application: application
    connections: {}
codeReference:
'https://github.com/myorg/repo/blob/abc1234/widgets.cpp#L1' #
    size: 10
    color: 'red'
  }
}
```

6. Deploy and verify:

```sh
rad deploy widget-app.bicep \
  --parameters environment=$(rad env show -o json | jq -r .id) \
--parameters application=$(rad app show <your-app> -o json | jq -r .id)

rad resource list Demo.Examples/widgets
```

Expect: Bicep compiles, deploy succeeds, resource appears with all four base props.

### Error path  — Bicep omits the required `environment`/ other auto-injected properties

Create `widget-missing-env.bicep`:

```bicep
extension radius
extension demo

resource w 'Demo.Examples/widgets@2026-06-01-preview' = {
  name: 'demo-widget-missing-env'
  properties: {
    // environment intentionally omitted — base marks it required.
    size: 5
    color: 'blue'
  }
}
```

## Type of change

<!--
Please select **one** of the following options that describes your change and delete the others. Clearly identifying the type of change you are making will help us review your PR faster, and is used in authoring release notes.
If you are making a bug fix or functionality change to Radius and do not have an associated issue link, please create one now.
-->
- This pull request fixes a bug in Radius and has an approved issue (issue link required).
- This pull request adds or changes features of Radius and has an approved issue (issue link required).
- This pull request is a minor refactor, code cleanup, test improvement, or other maintenance task and doesn't change the functionality of Radius (issue link optional).
- This pull request is a design document and only includes files in the eng/design-notes directory.

<!-- Please update the following to link the associated issue. This is required for some kinds of changes (see above). -->
Fixes: #issue_number

## Contributor checklist
Please verify that the PR meets the following requirements, where applicable:

- An overview of proposed schema changes is included in a linked GitHub issue.
    - [ ] Yes
    - [x] Not applicable
- A design document is added or updated under `eng/design-notes/` in this repository, if new APIs are being introduced.
    - [ ] Yes
    - [x] Not applicable
- The design document has been reviewed and approved by Radius maintainers/approvers.
    - [ ] Yes
    - [x] Not applicable
- A PR for [resource-types-contrib](https://github.com/radius-project/resource-types-contrib/) is created, if resource types or recipes are affected by the changes in this PR.
    - [ ] Yes
    - [x] Not applicable
- A PR for [dashboard](https://github.com/radius-project/dashboard/) is created, if the Radius Dashboard is affected by the changes in this PR.
    - [ ] Yes
    - [x] Not applicable
- A PR for the [documentation repository](https://github.com/radius-project/docs) is created, if the changes in this PR affect the documentation or any user facing updates are made.
    - [ ] Yes
    - [x] Not applicable

---------

Signed-off-by: Nithya Subramanian <nithyasu@microsoft.com>
Signed-off-by: sk593 <shruthikumar@microsoft.com>
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.

implementation: coderefrences

3 participants