Skip to content

Conversation

@its-mitesh-kumar
Copy link
Member

@its-mitesh-kumar its-mitesh-kumar commented Feb 4, 2026


PR Type

Enhancement


Description

  • Migrates bulk-import plugin to Backstage's New Frontend System (NFS)

  • Creates NFS-compatible alpha export with extension blueprints

  • Adds app-next test package for NFS functionality verification

  • Updates dependencies to support frontend plugin API


NFS App UI after changes

Repo Flow

Screen.Recording.2026-02-04.at.10.23.01.PM.mov

Scaffolder Flow with translation

Screen.Recording.2026-02-06.at.5.48.05.PM.mov

Legacy App UI after changes

Screen.Recording.2026-02-04.at.9.22.01.PM.mov

How to test

NFS App

  • yarn
  • yarn start:next
    For testing translation in NFS
  • Add below config in app-config.yaml
app:
  # NFS language selector configuration (for packages/app-next)
  extensions:
    - api:app/app-language:
        config:
          availableLanguages: ['en', 'de', 'fr']
          defaultLanguage: 'en'

Legacy App

  • yarn
  • yarn start

For testing Scaffolder Flow
Add below config in app-config.yaml

bulkImport:
  importAPI: 'scaffolder'
  importTemplate: template:default/create-pr-with-catalog-info
  instructionsEnabled: true
  instructionsDefaultExpanded: true
  instructionsSteps:
    - id: "step1"
      text: "Choose your source control platform"
      icon: "kind:component"
    - id: "step2"
      text: "Browse and select repositories"
      icon: "search"

✔️ Checklist

  • A changeset describing the change and affected packages. (more info)
  • Added or Updated documentation
  • Tests for new functionality and regression tests for bug fixes
  • Screenshots attached (for UI changes)

Diagram Walkthrough

flowchart LR
  A["Legacy Plugin"] -->|"alpha.tsx export"| B["NFS Extensions"]
  B -->|"ApiBlueprint"| C["BulkImportAPI"]
  B -->|"PageBlueprint"| D["Bulk Import Page"]
  B -->|"NavItemBlueprint"| E["Sidebar Navigation"]
  F["app-next Package"] -->|"tests NFS"| B
Loading

File Walkthrough

Relevant files
Configuration changes
package.json
NFS test app package configuration                                             

workspaces/bulk-import/packages/app-next/package.json

  • New test application package for NFS functionality
  • Includes Backstage frontend dependencies and CLI tools
  • Configured with start, build, test, and lint scripts
  • Depends on migrated bulk-import plugin via workspace reference
+62/-0   
index.html
NFS test app HTML template                                                             

workspaces/bulk-import/packages/app-next/public/index.html

  • HTML template for NFS test application
  • Includes metadata and favicon configuration
  • Contains root div for React mounting
  • Includes documentation comments about NFS test app purpose
+27/-0   
.eslintrc.js
NFS test app linting configuration                                             

workspaces/bulk-import/packages/app-next/.eslintrc.js

  • ESLint configuration using Backstage CLI factory
  • Ensures code quality standards for NFS test app
+1/-0     
package.json
Root workspace NFS startup script                                               

workspaces/bulk-import/package.json

  • Adds start:nfs script to run backend and app-next together
  • Enables testing of NFS functionality with single command
+1/-0     
Enhancement
App.tsx
NFS test app main application component                                   

workspaces/bulk-import/packages/app-next/src/App.tsx

  • Creates minimal Backstage app using NFS via createApp
  • Imports and registers bulk-import plugin with NFS features
  • Exports app root element for rendering in index.tsx
  • Includes comprehensive documentation on NFS architecture
+50/-0   
index.tsx
NFS test app entry point initialization                                   

workspaces/bulk-import/packages/app-next/src/index.tsx

  • Replaces translation export with NFS app initialization
  • Imports React DOM and renders app element to root
  • Adds Backstage CLI asset types support
  • Handles NFS pattern of exporting elements instead of components
+7/-1     
alpha.tsx
NFS plugin extensions and blueprints                                         

workspaces/bulk-import/plugins/bulk-import/src/alpha.tsx

  • New NFS-compatible export with extension blueprints
  • Implements ApiBlueprint for BulkImportAPI provisioning
  • Implements PageBlueprint for /bulk-import route
  • Implements NavItemBlueprint for sidebar navigation
  • Includes detailed documentation on permission handling differences
  • Re-exports translations for backward compatibility
+119/-0 
Dependencies
package.json
Plugin dependencies and export configuration                         

workspaces/bulk-import/plugins/bulk-import/package.json

  • Updates alpha export path from .ts to .tsx file extension
  • Adds @backstage/core-compat-api dependency for legacy compatibility
  • Adds @backstage/frontend-plugin-api dependency for NFS support
  • Updates typesVersions to reflect new alpha file extension
+4/-2     

Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
@its-mitesh-kumar its-mitesh-kumar requested review from a team, debsmita1 and rm3l as code owners February 4, 2026 11:56
@its-mitesh-kumar its-mitesh-kumar requested review from jrichter1 and removed request for a team February 4, 2026 11:56
@rhdh-gh-app
Copy link

rhdh-gh-app bot commented Feb 4, 2026

Changed Packages

Package Name Package Path Changeset Bump Current Version
app-next workspaces/bulk-import/packages/app-next none v0.0.1
@red-hat-developer-hub/backstage-plugin-bulk-import workspaces/bulk-import/plugins/bulk-import patch v7.0.1

@rhdh-qodo-merge
Copy link

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
🟢
No codebase code duplication found No new components were introduced in the PR code
Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Missing null guard: The code uses a non-null assertion on document.getElementById('root')! and does
not handle the edge case where the root element is missing, which can cause a runtime
crash instead of graceful degradation.

Referred Code
ReactDOM.createRoot(document.getElementById('root')!).render(app);

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@rhdh-qodo-merge
Copy link

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
Destructure Router for loader import

In the dynamic import for the page loader, destructure the Router component from
the imported module. This ensures the correct component is accessed and improves
code clarity.

workspaces/bulk-import/plugins/bulk-import/src/alpha.tsx [73]

-loader: () => import('./components').then(m => compatWrapper(<m.Router />)),
+loader: () => import('./components').then(({ Router }) => compatWrapper(<Router />)),
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly points out that destructuring the imported module is a safer and more explicit way to access the Router component. This improves code clarity and robustness against potential issues with how the module is structured.

Medium
Remove redundant development dependency from dependencies

Remove the @backstage/cli package from dependencies as it is a development tool
and should only be listed in devDependencies. This corrects its role and avoids
including it in production bundles.

workspaces/bulk-import/packages/app-next/package.json [21-46]

 "dependencies": {
-  "@backstage/cli": "^0.34.5",
   "@backstage/core-app-api": "^1.19.2",
   ...
 "devDependencies": {
   "@backstage/cli": "^0.34.5",
   "@backstage/test-utils": "^1.7.13",
   ...
 },

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 6

__

Why: The suggestion correctly points out that @backstage/cli is listed in both dependencies and devDependencies. Moving it to only devDependencies is the correct practice for a development tool, improving dependency management and potentially reducing production bundle size.

Low
Pin type dependency to specific version

Pin the @types/react-dom dependency to a specific version instead of using *.
This will improve build reproducibility and prevent unexpected breakages from
new major versions.

workspaces/bulk-import/packages/app-next/package.json [41-46]

 "devDependencies": {
   "@backstage/cli": "^0.34.5",
   "@backstage/test-utils": "^1.7.13",
   "@types/react": "^18.2.58",
-  "@types/react-dom": "*"
+  "@types/react-dom": "^18.2.19"
 },
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: The suggestion correctly identifies that using * for @types/react-dom is a bad practice for build stability and proposes pinning it to a version compatible with @types/react, which is a valid improvement for maintainability.

Low
High-level
Address sidebar item visibility regression

The migration to the New Frontend System (NFS) introduces a UX regression where
the sidebar item is always visible. This change should be documented in the
plugin's README to inform adopters.

Examples:

workspaces/bulk-import/plugins/bulk-import/src/alpha.tsx [80-98]
 * NOTE: This nav item is always visible in the sidebar. Unlike the legacy
 * BulkImportSidebarItem component, NavItemBlueprint does not support runtime
 * permission checking because:
 *
 * 1. Extension factories run at app startup, before user authentication
 * 2. NavItemBlueprint only accepts static data (title, icon, routeRef)
 * 3. React hooks like usePermission cannot be used in extension factories
 *
 * Permission checking is handled at the PAGE level instead. Users without
 * the required permissions will see a permission error when accessing the page.

 ... (clipped 9 lines)

Solution Walkthrough:

Before:

// In workspaces/bulk-import/plugins/bulk-import/src/alpha.tsx

/**
 * Nav Item Extension
 *
 * NOTE: This nav item is always visible in the sidebar. Unlike the legacy
 * BulkImportSidebarItem component, NavItemBlueprint does not support runtime
 * permission checking...
 * ...
 * Permission checking is handled at the PAGE level instead.
 */
const bulkImportNavItem = NavItemBlueprint.make({ ... });

// In README.md
... (no mention of the sidebar visibility change)

After:

// In workspaces/bulk-import/plugins/bulk-import/README.md

## New Frontend System (NFS) Support

This plugin provides an alpha export for the new frontend system.

### ⚠️ Breaking Change: Sidebar Item Visibility

When using the `NavItemBlueprint` from the `./alpha` export, the "Bulk Import"
sidebar item will always be visible, regardless of user permissions. This is a
limitation of the current NFS extension model.

Permission checks are enforced at the page level.

For applications requiring permission-based sidebar visibility, please continue
to use the legacy `BulkImportSidebarItem` component.
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies a UX regression and improves the PR by recommending the existing in-code documentation be moved to the README for better visibility to adopters.

Low
Possible issue
Add null check for root element

Replace the non-null assertion ! on document.getElementById('root') with a
proper null check. Throw an informative error if the element is not found to
make the application more robust.

workspaces/bulk-import/packages/app-next/src/index.tsx [22-23]

 // Render the app element directly (not as a component)
-ReactDOM.createRoot(document.getElementById('root')!).render(app);
+const root = document.getElementById('root');
+if (!root) {
+  throw new Error(
+    'Failed to find the root element. The app is not mounted in the DOM.',
+  );
+}
+ReactDOM.createRoot(root).render(app);
  • Apply / Chat
Suggestion importance[1-10]: 4

__

Why: This suggestion correctly identifies a potential runtime error and proposes a robust check. While valid, it has a smaller code footprint than another suggestion targeting the same issue, so it is preferred. The improvement enhances error handling and debuggability.

Low
  • More

Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
@its-mitesh-kumar its-mitesh-kumar marked this pull request as ready for review February 4, 2026 17:34
@openshift-ci openshift-ci bot requested a review from rohitkrai03 February 4, 2026 17:40
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 6, 2026

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