This document explains the major steps, script calls, and data flows in the sync-midstream.sh script.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Fetches upstream repos β Processes workspaces β Exports plugins β
Updates metadata β Generates catalog-index β Commits changes
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
upstream repos βββ€
ββ> Fetch & rsync ββ> overlay-repo/
ββ> Fetch & rsync ββ> workspaces/
overlay-repo/workspaces/*/source.json βββββ€
βΌ
Clone workspaces (sparse checkout)
βΌ
Apply overlays & patches (override-sources.sh)
βΌ
Export plugins (batchExportPlugins.sh)
βΌ
workspaces/*/plugins/*/dist-dynamic/
βββββββββββββββββββββββββββββββββββββββββββ΄ββββββββββββββββββββ
Update plugin_builds/*/*.json with registryReferences
βββββββββββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββ
default.packages.yaml (from rhdh repo) ββββ€
βΌ
generate_dpdy.py
βΌ
catalog-index/dynamic-plugins.default.yaml
plugin_builds/*/*.json ββββββββββββββββββββ€
overlay-repo/catalog-entities/ ββββββββββββ€
overlay-repo/workspaces/*/metadata/ βββββββ€
βΌ
generateCatalog
Index.py
βΌ
catalog-index/index.json
catalog-index/catalog-entities/marketplace/
βΌ
Git commit
Git push
Setup
* Parse CLI Arguments
β’ Get DWNSTM_BRANCH
Read upstream_repos.yml to determine:
β’ RHDH_BRANCH
β’ RHDH_VERSION
β’ BACKSTAGE_VERSION
FOR each repo in upstream_repos.yml (NUM_REPOS iterations)
1. Parse repo info:
β’ repo URL (github.com/redhat-developer/rhdh-*)
β’ branch (branch0 or branch1)
β’ destination_folder
2. Clone repo to TMPDIR/repo{i}/
git clone $repo -b $branch "$TMPDIR/repo${i}" --depth=3
3. Rsync content to midstream destination:
rsync -aPzq $TMPDIR/repo${i}/* ${ROOTPATH}/${destination_folder}/
Common destinations:
β’ overlay-repo/ (rhdh-dynamic-plugin-export-overlays)
β’ workspaces/ (backstage, community-plugins)
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Download scripts to build/scripts/ from rhdh-plugin-export-utils
β’ override-sources.sh
β’ export-dynamic.sh
β’ shorten-component-name.sh
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
FOR each overlay-repo/*/source.json file
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1. Parse source.json
β’ repo: https://github.com/backstage/community-plugins
β’ repo-ref: @backstage-community/plugin-quay-common@1.5.0
β’ folder_name: workspaces/ocm
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
2. Check if plugin is in SUPPORTED_PACKAGES (overlay-repo/rhdh-supported-packages.txt)
β’ If not found β Skip or Remove
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
3. Sparse clone plugin workspace into workspaces/{workspace_name}/
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
4. Remove plugins not in rhdh-supported-packages.txt from the plugins-list.yaml file; not all plugins in overlays repo will be productized
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
5. Generate manifest.json with generate-workspace-manifest.js
β’ Captures all package versions in workspace
β’ Resolves workspace:^ references
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
6. Apply overlays and patches (if APPLY_OVERLAY_PATCHES=1)
override-sources.sh
β’ Copies overlay-repo/{workspace}/overlay/
to workspaces/{workspace}/
β’ Applies patches from
overlay-repo/{workspace}/patches/
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
7. Export plugins (if not skipped) with batchExportPlugins.sh
β’ Finds all plugins in workspace
β’ For each plugin:
export-dynamic.sh (from rhdh-plugin-export-utils)
β’ yarn install --no-immutable
β’ yarn tsc / yarn tsc:full
β’ yarn build:all
β’ Create dist-dynamic/ artifacts
β’ Update package.json & yarn.lock
β’ For backend plugins: include embedded/ folder
Output: workspaces/{ws}/plugins/*/dist-dynamic/
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
8. Cleanup
β’ Remove examples/ folders
β’ Remove packages/backend, packages/app folders
β’ Remove node_modules/
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Apply sync-midstream.sh patches (if APPLY_SYNC_PATCHES=1)
β’ Apply all build/ci/*.patch files to the repo
β’ These are workspace-specific fixes downstream of the overlays repo; ideally this would be a no-op step
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
FOR each workspace with workspace: or backstage:^ refs
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1. Copy update-workspace.js to workspace
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
2. Transform workspace dependencies
update-workspace.js --update $BS_VERSION
β’ Replace workspace:^ references
β’ Replace backstage:^ references
β’ Pin to specific Backstage version
update-workspace.js --delete $UNNEEDED_PACKAGES
β’ Remove unneeded packages like e2e-test,app,app-next,backend
update-workspace.js --remove-patches
β’ Remove yarn dependency patch resolutions (backstage only)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
5. Fix .yarnrc.yml and package.json
β’ Set yarnPath
β’ Remove packageManager field (to support hermetic builds)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
6. Run yarn install / tsc / build (if YARN_INSTALL=1) to validate changes above
β’ install_tsc_build() function
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
FOR each plugin in SUPPORTED_PACKAGES
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1. Read plugin package.json
β’ Extract package_name
β’ Extract plugin_version
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
2. Update plugin_builds/{workspace}/{repo_name}.json
β’ Set registryReference:
quay.io/rhdh/{repo_name}:{RHDH_VERSION}--{plugin_version
β’ Set workspacePath: {workspace}/plugins/{plugin}
Example:
{
"backstage-community-plugin-ocm-backend": {
"registryReference":
"quay.io/rhdh/backstage-community-plugin-ocm-
backend:1.9.0--1.5.0",
"workspacePath": "ocm/plugins/ocm-backend"
}
}
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Update build/containerfiles/ with metadata
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1. Calculate next release number using getNextReleaseNum.sh
β’ Query for existing builds
β’ Increment release number in Containerfile
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
2. Update builder.Containerfile and index.Containerfile
β’ Add ENV variables (eg., RHDH_VERSION, BACKSTAGE_VERSION)
β’ Add LABEL metadata
β’ Set version and release
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Generate dynamic-plugins.default.yaml
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1. Download default.packages.yaml from rhdh repo
curl -sSLO "https://raw.githubusercontent.com/
redhat-developer/rhdh/refs/heads/${RHDH_BRANCH}/
default.packages.yaml"
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
2. Run generate_dpdy.py
Input:
-p catalog-index/default.packages.yaml
-d overlay-repo/
Process:
β’ Read all packages from default.packages.yaml
β’ For each package:
- Find metadata in overlay-repo/workspaces/
*/metadata/{package}.yaml
- Extract spec.dynamicArtifact
- Extract spec.appConfigExamples[0].content
β becomes pluginConfig
- Add integrity field if present
β’ Sort: enabled first, then alphabetically
Output:
-o catalog-index/dynamic-plugins.default.yaml
Format:
plugins:
- package: "@scope/pkg@version" or "./path"
disabled: true/false
integrity: sha512-... (optional)
pluginConfig:
<content from appConfigExamples>
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Generate catalog index
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
generateCatalogIndex.py (with optional --debug flag)
1. Move plugin definitions and static metadata (catalog-entities/marketplace)
From:
overlay-repo/catalog-entities/marketplace/
To:
catalog-index/catalog-entities/marketplace/
2. Copy workspace metadata files
Find all:
overlay-repo/workspaces/*/metadata/*.yaml
Copy to:
catalog-index/catalog-entities/marketplace/
packages/
These are Backstage catalog entity definitions
for individual plugins (Component kind)
3. Generate index.json from plugin_builds/
Read all:
plugin_builds/*/*.json
For each plugin:
β’ Extract registryReference
β’ Check if image exists (HTTP HEAD request)
β’ If exists, add to index
Combine digest into registryReference:
quay.io/rhdh/pkg@sha256:abc123...
Write to:
catalog-index/index.json
Format:
{
"plugin-name": {
"workspacePath": "ws/plugins/plugin",
"registryReference": "quay.io/rhdh/pkg@sha...",
"imageTag": "1.9.0--1.5.0",
"build-date": "...",
"vcs-ref": "...",
"upstream": "...",
"midstream": "..."
}
}
4. Update package YAML files with OCI references
For each plugin in index.json:
β’ Find matching YAML in:
- catalog-index/dynamic-plugins.default.yaml
- catalog-index/catalog-entities/marketplace/
packages/{plugin-name}.yaml
β’ Find existing entry:
- package: ./dynamic-plugins/dist/{plugin}
β’ Add OCI reference BEFORE the file path entry:
# Tag: 1.9.0--1.5.0, Build date: 2025-01-09
- package: oci://quay.io/rhdh/pkg@sha...!plugin
# new approach using oci images: to switch...
disabled: true
- package: ./dynamic-plugins/dist/{plugin}
pluginConfig:
...
This allows toggling between deprecated file-based wrappers and new
OCI-based plugin loading
5. Regenerate catalog-index/catalog-entities/marketplace/*/all.yaml files
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Cleanup after generation - remove unneeded files:
β’ overlay-repo/catalog-entities/
β’ overlay-repo/workspaces/*/metadata/
β’ catalog-index/catalog-entities/marketplace/README.md
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Update metadata in plugin_builds/*.json with generatePluginBuildInfo.py
β’ Adds additional metadata to plugin_builds/*.json
β’ Updates timestamps, git refs, etc.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Final cleanup
β’ Remove install-state.gz, node_modules, dist, dist-*
β’ Remove .yarn/cache/*
β’ Remove packages/app, packages/app-next, packages/backend
β’ Keep only embedded/, package.json, yarn.lock in dist-dynamic/
β’ Restore .pnp.cjs and .config-schema.json files (ignore changes)
β’ Check if index.Containerfile has only trivial changes
Add, commit, and push changes
β’ git add -f ...
β’ ${destination_folders}
β’ overlay-repo/
β’ workspaces/
β’ build/
β’ plugin_builds/
β’ upstream_repos.yml
β’ catalog-index/
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The catalog-index content is built from multiple sources:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
CATALOG-INDEX REFRESH FLOW
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
INPUT SOURCES:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1. overlay-repo/catalog-entities/marketplace/
β’ Static catalog entities (plugins, packages)
β’ Moved to catalog-index/catalog-entities/marketplace/
2. overlay-repo/workspaces/*/metadata/*.yaml
β’ Individual plugin metadata (Component kind)
β’ Contains: spec.packageName, spec.dynamicArtifact,
spec.version, spec.appConfigExamples
β’ Copied to catalog-index/catalog-entities/marketplace/
packages/
3. plugin_builds/*/*.json
β’ Contains registryReference for each plugin
β’ Format: quay.io/rhdh/{pkg}:{RHDH_VER}--{plugin_ver}
β’ Used to generate catalog-index/index.json
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
PROCESSING:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
generateCatalogIndex.py performs:
1. Moves marketplace/ folder
2. Copies workspace metadata/*.yaml files
3. Checks if OCI images exist (HTTP HEAD to quay.io)
4. Generates index.json with digest-pinned references
5. Updates YAML files with OCI references alongside file paths
6. Regenerates all.yaml Location files
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
OUTPUT:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
catalog-index/
βββ index.json
ββ Maps plugin names to OCI image refs with digests
βββ dynamic-plugins.default.yaml
ββ Updated with OCI references (disabled by default)
ββ catalog-entities/
ββ marketplace/
βββ plugins/
βββ all.yaml (Location kind)
ββ {plugin}.yaml
ββ packages/
βββ all.yaml (Location kind)
ββ {package}.yaml (updated with OCI refs)
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
DYNAMIC-PLUGINS.DEFAULT.YAML UPDATE FLOW
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
STEP 1: Download source file
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
curl -sSLO "https://raw.githubusercontent.com/
redhat-developer/rhdh/refs/heads/${RHDH_BRANCH}/
default.packages.yaml"
β catalog-index/default.packages.yaml
Contains:
packages:
enabled:
- package: "@scope/package"
integrity: sha512-...
disabled:
- package: "another-package"
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
STEP 2: Generate DPDY with Python script
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
generate_dpdy.py
-p catalog-index/default.packages.yaml
-d overlay-repo/
-o catalog-index/dynamic-plugins.default.yaml
Process:
1. Scan overlay-repo/workspaces/*/metadata/*.yaml
2. Index by spec.packageName and spec.dynamicArtifact
3. For each package in default.packages.yaml:
β’ Find matching metadata file
β’ Extract spec.dynamicArtifact (package path/name)
β’ Extract spec.appConfigExamples[0].content
β’ Build plugin entry:
- package: {dynamicArtifact}
disabled: {from default.packages.yaml}
integrity: {from default.packages.yaml, if external}
pluginConfig:
{content from appConfigExamples}
4. Sort: enabled plugins first, then alphabetically
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
STEP 3: Add OCI references (via generateCatalogIndex.py Task 4)
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
For each plugin with valid OCI image:
β’ Find entry in dynamic-plugins.default.yaml
β’ Add OCI reference BEFORE the existing file-based entry:
# Tag: 1.9.0--1.5.0, Build date: 2025-01-09
- package: oci://quay.io/rhdh/plugin@sha256:abc...!plugin
# new approach using oci images: to switch...
disabled: true
- package: ./dynamic-plugins/dist/plugin
disabled: false
pluginConfig:
...
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
OUTPUT:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
catalog-index/dynamic-plugins.default.yaml
β’ Contains all enabled and disabled plugins
β’ Each plugin has:
- OCI reference (disabled by default, for future use)
- File path reference (currently active)
- pluginConfig with example configuration
β’ Ready to be included in RHDH image builds
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
override-sources.sh Apply overlays and patches to workspaces sync-midstream.sh (Phase 4) Modified workspace files batchExportPlugins.sh Batch export all plugins in a workspace sync-midstream.sh (Phase 4) dist-dynamic/ folders export-dynamic.sh Export a single plugin (called by batchExportPlugins.sh) batchExportPlugins.sh dist-dynamic/package.json, yarn.lock, embedded/ generate-workspace-manifest.js Capture package versions for workspace:^ resolution sync-midstream.sh (Phase 4) manifest.json update-workspace.js Transform workspace dependencies sync-midstream.sh (Phase 5) Modified package.json, yarn.lock getNextReleaseNum.sh Query Konflux for next release number sync-midstream.sh (Phase 7) Release number for Containerfiles generate_dpdy.py Generate dynamic-plugins.default.yaml sync-midstream.sh (Phase 8) catalog-index/dynamic-plugins.default.yaml generateCatalogIndex.py Generate catalog index from plugin builds sync-midstream.sh (Phase 9) catalog-index/index.json, updated YAML files generatePluginBuildInfo.py Update plugin build metadata sync-midstream.sh (Phase 10) Updated plugin_builds/*.json
upstream_repos.yml- Defines repos to fetchoverlay-repo/rhdh-supported-packages.txt- List of plugins to includeoverlay-repo/workspaces/*/source.json- Source repo referencesoverlay-repo/workspaces/*/metadata/*.yaml- Plugin catalog entitiesoverlay-repo/workspaces/*/plugins-list.yaml- Plugins to exportoverlay-repo/workspaces/*/overlay/- Files to overlay onto workspacesoverlay-repo/workspaces/*/patches/- Patches to applyplugin_builds/*/*.json- Plugin registry references
workspaces/*/plugins/*/dist-dynamic/- Exported plugin artifactscatalog-index/index.json- Master plugin index with OCI refscatalog-index/dynamic-plugins.default.yaml- Plugin configuration filecatalog-index/catalog-entities/marketplace/packages/*.yaml- Individual plugin entitiescatalog-index/catalog-entities/marketplace/plugins/all.yaml- Location aggregatorcatalog-index/catalog-entities/marketplace/packages/all.yaml- Location aggregatorbuild/containerfiles/builder.Containerfile- Updated with metadatabuild/containerfiles/index.Containerfile- Updated with metadata