A comprehensive tool for building and exporting dynamic plugins for Red Hat Developer Hub (RHDH) from Backstage plugin source code.
- RHDH Dynamic Plugin Factory
The RHDH Plugin Factory automates the process of converting Backstage plugins into RHDH dynamic plugins. It provides:
- Source Repository Management: Clone and checkout plugin source repositories
- Patch & Overlay System: Apply custom modifications to plugin source code before exporting
- Dependency Management: Automated yarn installation with TypeScript compilation
- Dynamic Plugin Packaging: Build, export and package plugins using the RHDH CLI
- Container Image Publishing: Optionally push to container registries (Quay, OpenShift, etc.)
The RHDH Plugin Factory is distributed as a pre-built container image. It is recommended to use Podman for all platforms.
Pre-built container images are published to quay.io/rhdh-community/dynamic-plugins-factory with tags corresponding to the version of RHDH they were designed for:
# Pull the latest version
podman pull quay.io/rhdh-community/dynamic-plugins-factory:latest# Or pull a specific RHDH version
podman pull quay.io/rhdh-community/dynamic-plugins-factory:1.8The container requires specific capabilities and device access for building dynamic plugins:
- Volume Mounts: Mount your configuration, workspace, and/or output directories to the
/config,/workspaceand/outputsdirectories respectively - Device Access: Mount
/dev/fusefor filesystem operations (required for buildah) - SELinux Context: Use
:zflag for volume mounts on SELinux-enabled systems (RHEL/Fedora/CentOS)
The --device /dev/fuse flag passes the FUSE device from the Linux environment (native on Linux, or from Podman Machine's VM on macOS/Windows) to the container, enabling buildah operations.
podman run --rm -it \
--device /dev/fuse \
-v ./config:/config:z \
-v ./workspace:/workspace:z \
-v ./outputs:/outputs:z \
quay.io/rhdh-community/dynamic-plugins-factory:latest \
--workspace-path <path-to-workspace>Note: The --config-dir, --repo-path, and --output-dir options use default values of /config, /workspace, and /outputs respectively, which map to your local directories through volume mounts.
For local execution without containers, see CONTRIBUTING.md.
The factory expects the following directory structure:
./
├── config/ # Configuration directory (Can be set with --config-dir)
│ ├── .env # Optional: Override environment variables
│ ├── source.json # Source repository configuration
│ ├── plugins-list.yaml # List of plugins to build
│ ├── patches/ # Optional: Patch files to apply
│ └── <path-to-plugin-in-workspace>/overlays/ # Optional: Files to overlay on plugin source
├── workspace/ # Source code location (Can be set with --repo-path)
└── outputs/ # Build output directory (Can be set with --output-dir)This file contains required version settings and defaults for RHDH CLI:
# Tooling versions
RHDH_CLI_VERSION="1.8.0"Defines the source repository to clone:
{
"repo": "https://github.com/backstage/community-plugins",
"repo-ref": "main",
}Fields:
repo: Repository URL (HTTPS or SSH)repo-ref: Git reference (branch, tag, or commit SHA)
A list of plugin paths (with respect to root of workspace) to plugins to build along with optional build arguments:
# Simple plugins (no additional arguments)
plugins/todo:
plugins/todo-backend:# Plugins with embed packages
plugins/scaffolder-backend: --embed-package @backstage/plugin-scaffolder-backend-module-github# Multiple embed packages
plugins/search-backend: |
--embed-package @backstage/plugin-search-backend-module-catalog
--embed-package @backstage/plugin-search-backend-module-techdocsOverride default settings to publish to a remote image registry:
# Registry configuration (required only with --push-images)
REGISTRY_URL=quay.io
REGISTRY_USERNAME=your_username
REGISTRY_PASSWORD=your_password
REGISTRY_NAMESPACE=your_namespace
REGISTRY_INSECURE=false
# Logging
LOG_LEVEL=DEBUG
WORKSPACE_PATH=<path_to_workspace_with_respect_to_plugin_repo_root>LOG_LEVEL can be set to one of DEBUG, INFO (default), WARN, ERROR, or CRITICAL
WORKSPACE_PATH can be set in lieu of the --workspace-path argument
WARNING: This is a destructive operation
Patches and overlays modify files directly in the
--repo-pathdirectory. These operations are destructive and will permanently change the repository contents.
- When using
--use-localwith a local repository, patches and overlays WILL modify your local files- Consider using version control OR cloning a fresh copy of your repository if you need to preserve the original state
Place .patch files to apply modifications to the source code:
config/
└── patches/
└── 001-fix-dependency.patchPatches are applied using the override-sources.sh script before building.
See the AWS ECS plugin example config for an example on how patches are applied
Place files that should be copied over the source code:
config/
└── plugins/
└── my-plugin/
└── overlay/
└── custom-config.tsSee the TODO plugin example config and Gitlab plugin example config for an example on using overlays.
| Option | Default | Description |
|---|---|---|
--config-dir |
/config |
Configuration directory containing source.json, plugins-list.yaml, patches, and overlays |
--repo-path |
/workspace |
Path where plugin source code will be cloned/stored |
--workspace-path |
(required) | Path to the workspace from repository root (e.g., workspaces/todo) |
--output-dir |
/outputs |
Directory for build artifacts (.tgz files and container images) |
--push-images / --no-push-images |
--no-push-images |
Whether to push container images to registry. Defaults to not pushing if no argument is provided |
--use-local |
false |
Use local repository instead of cloning from source.json |
--log-level |
INFO |
Logging level: DEBUG, INFO, WARNING, ERROR, CRITICAL |
--verbose |
false |
Show verbose output with file and line numbers |
When using the container, you can mount directories based on your needs:
| Volume Mount | Required? | Purpose | When to Use |
|---|---|---|---|
-v ./config:/config:z |
Required | Configuration files | Always - contains your plugins-list.yaml, source.json, patches, and overlays |
-v ./workspace:/workspace:z |
Optional | Source code location | Only if using --use-local OR if you want to preserve/inspect the cloned/patched remote repository |
-v ./outputs:/outputs:z |
Optional | Build artifacts | Only if you want the output .tgz files saved locally (otherwise they stay in the container) |
Important: These volume mount paths (/config, /workspace, /outputs) correspond to the default values of --config-dir, --repo-path, and --output-dir. If you override these arguments with custom paths, adjust your volume mounts accordingly.
Note: Use the :z flag for systems with SELinux enabled (RHEL/Fedora/CentOS). On other systems, you can omit it.
The following examples demonstrate common use cases with the container image. All examples assume you have the necessary configuration files (source.json, plugins-list.yaml, and optionally patches/overlays) in your configuration directory. See the Configuration section for details.
This minimal example builds the TODO plugins without saving the workspace or output files locally:
podman run --rm -it \
--device /dev/fuse \
-v ./examples/example-config-todo:/config:z \
quay.io/rhdh-community/dynamic-plugins-factory:latest \
--workspace-path workspaces/todoThis will clone the repository, build the plugins, and NOT push the result to a remote repository.
This example builds plugins and saves the .tgz files to your local ./outputs/ directory:
podman run --rm -it \
--device /dev/fuse \
-v ./config:/config:z \
-v ./outputs:/outputs:z \
quay.io/rhdh-community/dynamic-plugins-factory:latest \
--workspace-path workspaces/todoThis will clone the repository specified in ./config/source.json, build the plugins listed in ./config/plugins-list.yaml, and save the .tgz files to ./outputs/.
This example builds plugins and pushes them directly to a container registry (no local .tgz files saved).
First, create a ./config/.env file with your registry credentials:
REGISTRY_URL=quay.io
REGISTRY_USERNAME=myuser
REGISTRY_PASSWORD=mytoken
REGISTRY_NAMESPACE=mynamespaceThen run the factory with --push-images:
podman run --rm -it \
--device /dev/fuse \
-v ./config:/config:z \
quay.io/rhdh-community/dynamic-plugins-factory:latest \
--workspace-path workspaces/announcements \
--push-imagesThe factory will automatically read the load the environmental variables from ./config/.env.
If you already have the source code locally, use the --use-local flag and mount your existing workspace:
podman run --rm -it \
--device /dev/fuse \
-v ./config:/config:z \
-v /path/to/existing-workspace:/workspace:z \
-v ./outputs:/outputs:z \
quay.io/rhdh-community/dynamic-plugins-factory:latest \
--workspace-path path/to/workspace \
--use-localNote: When using --use-local, patches and overlays will still be applied to your local repository. Make sure you have backups or are using version control.
The factory also produces the following outputs in the directory specified by --output-dir:
outputs/
├── plugin-name-dynamic-1.0.0.tgz # Plugin tarball
├── plugin-name-dynamic-1.0.0.tgz.integrity # Integrity checksum
└── ...When --push-images is enabled, images are tagged as:
${REGISTRY_URL}/${REGISTRY_NAMESPACE}/plugin-name-dynamic:1.0.0NOTE: If the repository name (ex: plugin-name-dynamic) in the namespace specified by REGISTRY_NAMESPACE does not exist, the dynamic plugin factory will create a new registry. Depending on the registry specified by REGISTRY_URL, the newly created repository may be private. This will be the case for quay.io.
The examples directory contains ready-to-use configuration examples demonstrating different use cases and features.
| Example | Description | Details |
|---|---|---|
| TODO | Basic workspace with custom scalprum-config | View README |
| GitLab | Overlays for non-BCP workspace format | View README |
| AWS ECS | Patches and embed packages in plugins-list.yaml | View README |
Build the TODO plugin from Backstage community plugins:
podman run --rm -it \
--device /dev/fuse \
-v ./examples/example-config-todo:/config:z \
quay.io/rhdh-community/dynamic-plugins-factory:latest \
--workspace-path workspaces/todo \
--no-push-imagesThis example includes:
- Custom
scalprum-config.jsonconfiguration - Standard Backstage Community Plugins (BCP) workspace format
- Both frontend and backend plugins in the workspace
For detailed instructions, package verification steps, and additional examples, see the individual README files linked in the table above.
For users who want to run the factory locally without containers or contribute to the project, see CONTRIBUTING.md.
To learn more about how dynamic plugins work refer to the dynamic plugins documentation in the RHDH Repository