Thank you for your interest in contributing to the RHDH Dynamic Plugin Factory! This guide will help you get started with development, testing, and submitting contributions.
- Getting Started
- Development Environment
- Project Structure
- Running Tests
- Development Workflow
- Code Quality Standards
- Submitting Changes
-
Fork the repository on GitHub by clicking the "Fork" button
-
Clone your fork locally:
git clone https://github.com/YOUR_USERNAME/rhdh-dynamic-plugin-factory
cd rhdh-dynamic-plugin-factory3. Add the upstream remote:
git remote add upstream https://github.com/redhat-developer/rhdh-dynamic-plugin-factoryYou can develop using either containers or local setup.
Container-based development provides consistency and isolation.
-
Podman installed (installation guide)
-
Podman Machine initialized (macOS/Windows):
podman machine init podman machine start
podman build -t rhdh-dynamic-plugin-factory:dev .Run the factory with your local build:
podman run --rm -it \
--device /dev/fuse \
-v ./config:/config:z \
-v ./source:/source:z \
-v ./outputs:/outputs:z \
rhdh-dynamic-plugin-factory:dev \
--workspace-path workspaces/todo \
--no-push-imagesFollow instructions in the main Usage Docs for container usage and replace image with your locally built image.
- Python: 3.10 or higher
- Node.js: 22 or higher (version specified in
default.env) - Corepack: To configure the yarn package managers on a project to project basis
- Git: For cloning repositories
- Buildah: Required for building and pushing container images
- Linux:
dnf install buildahorapt install buildah - macOS: Not directly supported (use Podman containers)
- Windows: Not directly supported (use Podman containers)
- Linux:
Create and activate a Python virtual environment:
python -m venv venv
source venv/bin/activate# Install Python dependencies
pip install -r requirements.txt -r requirements.dev.txtThe default.env file contains default settings:
# View current settings
cat default.env
# Create a custom .env file (optional)
cp default.env .envTest that the CLI works:
python -m src.rhdh_dynamic_plugin_factory --helpOnce you have the local environment set up, you can run the factory directly with Python.
python -m src.rhdh_dynamic_plugin_factory \
--config-dir ./config \
--workspace-path workspaces/todo \
--repo-path ./source \
--output-dir ./outputs \
--cleanCreate a ./config/.env file with your registry credentials:
REGISTRY_URL=quay.io
REGISTRY_USERNAME=myuser
REGISTRY_PASSWORD=mytoken
REGISTRY_NAMESPACE=mynamespaceThen run:
python -m src.rhdh_dynamic_plugin_factory \
--config-dir ./config \
--workspace-path workspaces/announcements \
--repo-path ./source/ \
--push-images \
--cleanThe factory will automatically read the registry credentials from ./config/.env.
python -m src.rhdh_dynamic_plugin_factory \
--config-dir ./config \
--repo-path ./source \
--workspace-path . \
--output-dir ./outputs \
--use-localrhdh-dynamic-plugin-factory/
├── src/rhdh_dynamic_plugin_factory/
│ ├── __init__.py # Package initialization and public API
│ ├── __main__.py # Package entry point
│ ├── __version__.py # Package version definition
│ ├── cli.py # CLI implementation and argument parsing
│ ├── config.py # Configuration classes and validation
│ ├── constants.py # Shared constants and configuration values
│ ├── exceptions.py # Custom exception hierarchy
│ ├── logger.py # Logging setup and utilities
│ ├── plugin_list_config.py # Plugin list YAML handling and build-arg computation
│ ├── source_config.py # Source repository and multi-workspace configuration
│ └── utils.py # Utility functions
├── scripts/
│ ├── export-workspace.sh # Plugin export script (called by CLI)
│ └── override-sources.sh # Patch/overlay application script
├── tests/
│ ├── __init__.py
│ ├── conftest.py # Pytest fixtures and configuration
│ ├── test_cli.py # CLI argument parsing tests
│ ├── test_config_discover_and_build_args.py # Plugin discovery and build-arg tests
│ ├── test_config_export_plugins.py # Plugin export tests
│ ├── test_config_load_from_env.py # Environment loading tests
│ ├── test_config_patches_and_overlays.py # Patch/overlay tests
│ ├── test_config_registry.py # Registry configuration tests
│ ├── test_multi_workspace.py # Multi-workspace mode tests
│ ├── test_plugin_list_config.py # Plugin list and build-arg tests
│ ├── test_source_config.py # Source configuration tests
│ └── test_utils.py # Utility function tests
├── examples/ # Example configuration sets
│ ├── example-config-todo/
│ ├── example-config-gitlab/
│ ├── example-config-aws-ecs/
│ ├── example-config-backstage-devtools/
│ ├── example-config-toolbox/
│ ├── example-config-usage-statistics/
│ └── example-config-multi-workspace/
├── .github/ # GitHub Actions CI/CD
├── resources/
│ ├── rhdh/yarn.lock # RHDH yarn.lock used for dependency matching in `plugins-list.yaml` private dependency resolution
│ └── metadata.json # Package metadata
├── .cursor/rules/ # Development guidelines
│ ├── commit-standards.mdc
│ ├── development-workflow.mdc
│ ├── documentation-standards.mdc
│ ├── github-actions-workflow.mdc
│ ├── integration-tests.mdc
│ ├── planning-process.mdc
│ ├── pytest-unit-tests.mdc
│ ├── python-code-quality.mdc
│ └── shell-code-quality.mdc
├── .dockerignore
├── .gitignore
├── CONTRIBUTING.md # Contributor guidelines
├── default.env # Default environment settings
├── Dockerfile # Container image definition
├── LICENSE
├── pyproject.toml # Python project configuration
├── pytest.ini # Pytest configuration
├── README.md # Main user documentation
├── renovate.json # Renovate dependency update configuration
├── requirements.dev.txt # Python development dependencies
└── requirements.txt # Python runtime dependenciescli.py: Handles command-line arguments, orchestrates the build process (single and multi-workspace)config.py: Loads and validates configuration from files and environmentconstants.py: Shared constants (plugin roles, skip directories, native module markers)exceptions.py: Custom exception hierarchy (PluginFactoryError,ConfigurationError,ExecutionError)logger.py: Configures structured logging with color outputplugin_list_config.py: Plugin list YAML loading/saving and build-argument computation logicsource_config.py: Source repository configuration, git cloning, and multi-workspace discoveryutils.py: Helper functions for file operations, subprocess executionexport-workspace.sh: Shell script that calls the RHDH CLI to export pluginsoverride-sources.sh: Applies patches and overlays to source code
The project uses pytest for testing.
pytest tests/pytest tests/ -vpytest tests/test_config.py -v# Run a specific test class
pytest tests/test_config.py::TestPluginFactoryConfigLoadFromEnv -v
# Run a specific test method
pytest tests/test_config.py::TestPluginFactoryConfigLoadFromEnv::test_load_from_env_valid_configuration -vpytest tests/ --cov=src/rhdh_dynamic_plugin_factory --cov-report=term-missingE2E tests require a built image of the factory which is provided via the E2E_IMAGE environmental variable.
Use the -n auto --dist loadscope arguments to run tests in parallel.
E2E_IMAGE=quay.io/rhdh-community/dynamic-plugins-factory:latest pytest -m e2e -n auto --dist loadscopeThis will show which lines of code are not covered by tests.
When adding new features:
- Write tests first (Test-Driven Development)
- Test both success and failure cases
- Use descriptive test names:
test_<what>_<condition>_<expected> - Use fixtures from
conftest.pyfor common setup - Mock external dependencies (file system, subprocess calls)
Example test structure:
def test_config_loads_from_valid_file(tmp_path):
"""Test that configuration loads successfully from a valid file."""
# Arrange
config_file = tmp_path / "config.json"
config_file.write_text('{"key": "value"}')
# Act
result = load_config(config_file)
# Assert
assert result["key"] == "value"# Update your main branch
git checkout main
git pull upstream main
# Create a new feature branch
git checkout -b feature/my-new-feature- Write code following the Code Quality Standards
- Add or update tests
- Update documentation if needed
# Run tests
pytest tests/
# Check code coverage
pytest tests/ --cov=src/rhdh_dynamic_plugin_factory --cov-report=term-missing
# Check types (if using mypy)
mypy src/Follow the Conventional Commits format:
git add .
git commit -m "feat: add support for custom plugin configurations"Commit types:
feat:New featurefix:Bug fixdocs:Documentation changestest:Test additions or changesrefactor:Code refactoringchore:Maintenance tasksci:CI/CD changes
See .cursor/rules/commit-standards.mdc for detailed commit guidelines.
git push origin feature/my-new-feature- Go to your fork on GitHub
- Click "Pull Request"
- Select your branch and provide a clear description:
- What changes were made
- Why they were needed
- Any breaking changes
- Related issues
Follow the guidelines in .cursor/rules/python-code-quality.mdc:
- PEP 8: Follow Python style guidelines
- Type Hints: Use type annotations for function signatures
- Docstrings: Use Google-style docstrings for all public functions/classes
- Error Handling: Use specific exception types, provide helpful error messages
- Imports: Group and sort imports (stdlib, third-party, local)
Example:
def process_config(config_path: Path, validate: bool = True) -> Dict[str, Any]:
"""Process and validate a configuration file.
Args:
config_path: Path to the configuration file.
validate: Whether to validate the configuration.
Returns:
Dictionary containing the processed configuration.
Raises:
FileNotFoundError: If the configuration file doesn't exist.
ValueError: If the configuration is invalid.
"""
if not config_path.exists():
raise FileNotFoundError(f"Configuration file not found: {config_path}")
# Implementation here
passFollow the guidelines in .cursor/rules/shell-code-quality.mdc:
- Follow Google Shell Style Guide
- Use
#!/usr/bin/env bashshebang - Enable strict mode:
set -euo pipefail - Quote all variables
- Use functions for reusable logic
- Add comments for complex operations
Follow the guidelines in .cursor/rules/documentation-standards.mdc:
- Use Google-style docstrings
- Keep documentation up-to-date with code changes
- Include examples in docstrings when helpful
- Update README.md for user-facing changes
- Add comments for complex logic
Before submitting:
- Tests pass locally
- Code follows style guidelines
- Documentation is updated
- Commit messages follow conventional format
- No merge conflicts with main branch
- Changes are in a feature branch (not main)
- Maintainers will review your PR
- Address any feedback or requested changes
- Once approved, a maintainer will merge your PR
# Update your local repository
git checkout main
git pull upstream main
# Delete your feature branch (optional)
git branch -d feature/my-new-feature- Issues: Search existing GitHub Issues or create a new one
- Discussions: Join the conversation in GitHub Discussions
- Documentation: Check the README.md and example configurations
By contributing to this project, you agree that your contributions will be licensed under the same license as the project (see LICENSE file).
This project follows a Code of Conduct to ensure an inclusive and welcoming environment for all contributors. Please be respectful and professional in all interactions.
Thank you for contributing to RHDH Dynamic Plugin Factory!