Skip to content

feat(orchestrator): support nested objects in rjsf-widgets config - #4461

Merged
karthikjeeyar merged 4 commits into
redhat-developer:mainfrom
lokanandaprabhu:feat/orchestrator-nested-rjsf-widgets-config
Sep 1, 2026
Merged

feat(orchestrator): support nested objects in rjsf-widgets config#4461
karthikjeeyar merged 4 commits into
redhat-developer:mainfrom
lokanandaprabhu:feat/orchestrator-nested-rjsf-widgets-config

Conversation

@lokanandaprabhu

@lokanandaprabhu lokanandaprabhu commented Aug 25, 2026

Copy link
Copy Markdown
Member

Story - https://redhat.atlassian.net/browse/RHIDP-16437

Summary

Adds support for nested objects in orchestrator.rjsf-widgets configuration, enabling Platform Engineers to organize widget parameters hierarchically.

Changes

  • Config Schema: Updated config.d.ts to accept [key: string]: any instead of [key: string]: string
  • Tests: Added comprehensive test coverage for nested path resolution
  • Documentation: Updated orchestratorFormWidgets.md with nested configuration examples
  • Backward Compatible: Existing flat string keys continue to work and can be mixed with nested structures

Video

Screen.Recording.2026-08-25.at.11.09.31.AM.mov

Example Configuration

orchestrator:
  rjsf-widgets:
    # Nested structure
    app-registration:
      xParams:
        name: app-registration
        version: 0.21.0
    # Flat keys still work
    defaultEnvironment: production

How to Test

1. Add Configuration

Add to your app-config.local.yaml:

orchestrator:
  rjsf-widgets:
    app-registration:
      xParams:
        name: app-registration
        version: 0.21.0
      environment: dev
    cloud-run:
      xParams:
        name: cloud-run
        version: 1.0.0
    defaultEnvironment: production

2. Create Test Workflow

Workflow: test-nested-config.sw.yaml

id: test-nested-config
version: "1.0"
specVersion: "0.8"
name: Test Nested rjsf-widgets Configuration
description: "Demonstrates nested and flat config values"
dataInputSchema: schemas/test-nested-config__main-schema.json
start: StartState
functions:
  - name: successResult
    type: expression
    operation: '{ "result": { "message": "Config test completed" } }'
states:
  - name: StartState
    type: operation
    actions:
      - name: setOutput
        functionRef:
          refName: successResult
    end: true

Schema: schemas/test-nested-config__main-schema.json

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Test Nested Config",
  "type": "object",
  "properties": {
    "flatConfig": {
      "type": "string",
      "title": "Flat Config Value",
      "ui:widget": "ActiveText",
      "ui:props": {
        "ui:text": "**Environment:** $${{rjsfConfig.defaultEnvironment}}"
      }
    },
    "nestedConfig": {
      "type": "string",
      "title": "Nested Config Values",
      "ui:widget": "ActiveText",
      "ui:props": {
        "ui:text": "## App Registration\n\n- **Name:** $${{rjsfConfig.app-registration.xParams.name}}\n- **Version:** $${{rjsfConfig.app-registration.xParams.version}}\n- **Env:** $${{rjsfConfig.app-registration.environment}}"
      }
    },
    "mixedExample": {
      "type": "string",
      "title": "Mixed Config Summary",
      "ui:widget": "ActiveText",
      "ui:props": {
        "ui:text": "# Summary\n\nGlobal: **$${{rjsfConfig.defaultEnvironment}}**\n\nWidgets:\n- $${{rjsfConfig.app-registration.xParams.name}} v$${{rjsfConfig.app-registration.xParams.version}}\n- $${{rjsfConfig.cloud-run.xParams.name}} v$${{rjsfConfig.cloud-run.xParams.version}}"
      }
    }
  }
}

3. Run Tests

yarn workspace @red-hat-developer-hub/backstage-plugin-orchestrator-form-widgets test useTemplateUnitEvaluator

All 10 tests should pass, including new tests for:

  • Nested path resolution
  • Multiple widget namespaces
  • Mixed flat and nested keys
  • Missing paths return undefined

4. Test in UI

  1. Start backend: yarn dev
  2. Navigate to Orchestrator → Workflows
  3. Run "Test Nested rjsf-widgets Configuration" workflow
  4. Verify the form displays:
    • Flat config: defaultEnvironment → "production"
    • Nested config: app-registration.xParams.name → "app-registration"
    • All values rendered as markdown in ActiveText widgets

Customer Request

Resolves customer feature request for hierarchical widget parameter organization (xParams configuration).

- Update config schema to accept nested objects in orchestrator.rjsf-widgets
- Add tests for nested path resolution (flat, nested, mixed scenarios)
- Update documentation with nested configuration examples
- Maintain backward compatibility with existing flat string keys

Templates can now reference nested values using dot-path notation:
$${{rjsfConfig.widget-id.xParams.name}}

Resolves customer request for hierarchical widget parameter organization.
@rhdh-gh-app

rhdh-gh-app Bot commented Aug 25, 2026

Copy link
Copy Markdown

Important

This PR includes changes that affect public-facing API. Please ensure you are adding/updating documentation for new features or behavior.

Changed Packages

Package Name Package Path Changeset Bump Current Version
@red-hat-developer-hub/backstage-plugin-orchestrator-common workspaces/orchestrator/plugins/orchestrator-common minor v3.10.0

Add jest.Mock type casts to fix TypeScript compilation errors:
- mockImplementation expects parameters
- mockReturnValue can accept undefined
Only orchestrator-common has published code changes (config.d.ts).
orchestrator-form-widgets only has test changes which don't require a changeset.
@codecov

codecov Bot commented Aug 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 61.61%. Comparing base (99da62c) to head (c945f62).
⚠️ Report is 52 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4461      +/-   ##
==========================================
- Coverage   61.62%   61.61%   -0.01%     
==========================================
  Files        2541     2540       -1     
  Lines      101912   101875      -37     
  Branches    28555    28553       -2     
==========================================
- Hits        62800    62775      -25     
+ Misses      37308    37296      -12     
  Partials     1804     1804              
Flag Coverage Δ *Carryforward flag
adoption-insights 84.55% <ø> (ø) Carriedforward from 1c2ddaf
ai-integrations 67.70% <ø> (ø) Carriedforward from 1c2ddaf
app-defaults 48.37% <ø> (ø) Carriedforward from 1c2ddaf
augment 46.67% <ø> (ø) Carriedforward from 1c2ddaf
boost 79.84% <ø> (ø) Carriedforward from 1c2ddaf
bulk-import 72.79% <ø> (ø) Carriedforward from 1c2ddaf
cost-management 13.55% <ø> (ø) Carriedforward from 1c2ddaf
dcm 72.09% <ø> (ø) Carriedforward from 1c2ddaf
e2e-adoption-insights 60.00% <ø> (ø) Carriedforward from 1c2ddaf
e2e-extensions 62.13% <ø> (ø) Carriedforward from 1c2ddaf
e2e-global-header 49.45% <ø> (ø) Carriedforward from 1c2ddaf
e2e-homepage 61.11% <ø> (ø) Carriedforward from 1c2ddaf
e2e-intelligent-assistant 46.68% <ø> (ø) Carriedforward from 1c2ddaf
e2e-orchestrator 49.52% <ø> (ø) Carriedforward from 1c2ddaf
e2e-quickstart 55.21% <ø> (ø) Carriedforward from 1c2ddaf
e2e-scorecard 50.21% <ø> (ø) Carriedforward from 1c2ddaf
e2e-theme 16.36% <ø> (ø) Carriedforward from 1c2ddaf
extensions 56.59% <ø> (ø) Carriedforward from 1c2ddaf
global-floating-action-button 71.18% <ø> (ø) Carriedforward from 1c2ddaf
global-header 66.50% <ø> (ø) Carriedforward from 1c2ddaf
homepage 47.46% <ø> (ø) Carriedforward from 1c2ddaf
install-dynamic-plugins 58.57% <ø> (ø) Carriedforward from 1c2ddaf
intelligent-assistant 75.35% <ø> (ø) Carriedforward from 1c2ddaf
konflux 91.98% <ø> (ø) Carriedforward from 1c2ddaf
lightspeed 69.02% <ø> (ø) Carriedforward from 1c2ddaf
mcp-integrations 83.40% <ø> (ø) Carriedforward from 1c2ddaf
orchestrator 70.87% <ø> (+0.01%) ⬆️
quickstart 63.74% <ø> (ø) Carriedforward from 1c2ddaf
sandbox 79.56% <ø> (ø) Carriedforward from 1c2ddaf
scorecard 87.40% <ø> (ø) Carriedforward from 1c2ddaf
theme 88.91% <ø> (ø) Carriedforward from 1c2ddaf
translations 5.12% <ø> (ø) Carriedforward from 1c2ddaf
x2a 79.20% <ø> (ø) Carriedforward from 1c2ddaf

*This pull request uses carry forward flags. Click here to find out more.


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 99da62c...c945f62. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@lholmquist

Copy link
Copy Markdown
Member

I'm not sure if I'm missing something with the configuration, but this is what I'm seeing on the UI:

Screenshot 2026-08-25 at 9 06 57 AM

Here is the workflow definition and the schema:

Screenshot 2026-08-25 at 9 07 58 AM

and what i added to my app-config:

Screenshot 2026-08-25 at 9 08 49 AM

@lokanandaprabhu

Copy link
Copy Markdown
Member Author

@lholmquist The schema in the video demonstrates a more detailed example with grouped sections (4 objects with nested properties), while the PR description includes a simplified version (3 flat properties) to keep the testing instructions concise.

Both schemas work correctly and demonstrate the same nested config capability. If you'd like to see the exact schema from the video, you can use:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Test Nested rjsf-widgets Configuration",
  "type": "object",
  "description": "Demonstrates accessing both nested and flat configuration values",
  "properties": {
    "flatConfigDisplay": {
      "type": "object",
      "title": "Flat Configuration Values",
      "properties": {
        "defaultEnvironment": {
          "type": "string",
          "title": "Default Environment (Flat Config)",
          "ui:widget": "ActiveText",
          "ui:props": {
            "ui:text": "**Default Environment:** $${{rjsfConfig.defaultEnvironment}}"
          }
        }
      }
    },
    "nestedConfigDisplay": {
      "type": "object",
      "title": "Nested Configuration Values",
      "properties": {
        "appRegistrationInfo": {
          "type": "string",
          "title": "App Registration Widget Config",
          "ui:widget": "ActiveText",
          "ui:props": {
            "ui:text": "## App Registration Widget\n\n- **Name:** $${{rjsfConfig.app-registration.xParams.name}}\n- **Version:** $${{rjsfConfig.app-registration.xParams.version}}\n- **Environment:** $${{rjsfConfig.app-registration.environment}}"
          }
        },
        "cloudRunInfo": {
          "type": "string",
          "title": "Cloud Run Widget Config",
          "ui:widget": "ActiveText",
          "ui:props": {
            "ui:text": "## Cloud Run Widget\n\n- **Name:** $${{rjsfConfig.cloud-run.xParams.name}}\n- **Version:** $${{rjsfConfig.cloud-run.xParams.version}}"
          }
        }
      }
    },
    "mixedConfigDisplay": {
      "type": "object",
      "title": "Mixed Configuration Example",
      "properties": {
        "summary": {
          "type": "string",
          "title": "Configuration Summary",
          "ui:widget": "ActiveText",
          "ui:props": {
            "ui:text": "# Configuration Summary\n\n**Global:** $${{rjsfConfig.defaultEnvironment}}\n\n**Widgets:**\n- $${{rjsfConfig.app-registration.xParams.name}} v$${{rjsfConfig.app-registration.xParams.version}}\n- $${{rjsfConfig.cloud-run.xParams.name}} v$${{rjsfConfig.cloud-run.xParams.version}}"
          }
        }
      }
    }
  }
}

The key feature this PR enables is that orchestrator.rjsf-widgets now officially supports nested objects with proper TypeScript typing, testing, and documentation. Both schemas demonstrate this works correctly.

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

worked like the video

Comment thread workspaces/orchestrator/plugins/orchestrator-common/config.d.ts Outdated
Address review feedback from @karthikjeeyar:
- Change type from 'any' to 'string | { [key: string]: any }'
- Prevents misconfiguration errors when users accidentally use numbers
- Provides better type safety while maintaining nested object support
- Update JSDoc to document value type requirements
@sonarqubecloud

sonarqubecloud Bot commented Sep 1, 2026

Copy link
Copy Markdown

@karthikjeeyar
karthikjeeyar merged commit 213b75e into redhat-developer:main Sep 1, 2026
19 checks passed
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