From ba3b2d520e392b098dc619e2112af0353f25c6f7 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Thu, 12 Feb 2026 03:25:09 +0000 Subject: [PATCH 01/19] fix(ci): fix OSD-GCP operator deployment failures (RHDHBUGS-1136) Fix multiple issues causing OSD-GCP operator CI jobs to fail: 1. Fix orchestrator plugin version mismatch in OSD-GCP diff files. The overlay tag referenced 5.3.1 but the base values use 5.1.0, causing a duplicate plugin configuration error and CrashLoopBackOff. 2. Skip Serverless and Serverless Logic operator installation on OSD-GCP jobs. These operators are only needed for orchestrator workflows, which are disabled on OSD-GCP. The Serverless Logic operator was timing out after 300s on OSD-GCP clusters. 3. Add external Postgres setup for the showcase-runtime deployment. The runtime CRD uses enableLocalDb: false and expects postgres-crt and postgres-cred secrets, which were not being created, causing the deployment to fail with "Secret postgres-crt not found". 4. Remove duplicate prepare_operator() call from the OSD-GCP deployment path. It is already called in handle_ocp_operator() before the OSD-GCP branch is entered. --- .ibm/pipelines/jobs/ocp-operator.sh | 30 +++++++++++++++++-- .ibm/pipelines/utils.sh | 11 +++++-- .../diff-values_showcase-rbac_OSD-GCP.yaml | 4 +-- .../diff-values_showcase_OSD-GCP.yaml | 4 +-- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/.ibm/pipelines/jobs/ocp-operator.sh b/.ibm/pipelines/jobs/ocp-operator.sh index b816850710..dea58e6b93 100644 --- a/.ibm/pipelines/jobs/ocp-operator.sh +++ b/.ibm/pipelines/jobs/ocp-operator.sh @@ -43,7 +43,7 @@ initiate_operator_deployments() { initiate_operator_deployments_osd_gcp() { log::info "Initiating Operator-backed deployments on OSD-GCP (orchestrator disabled)" - prepare_operator + # Note: prepare_operator is already called in handle_ocp_operator() before this function namespace::configure "${NAME_SPACE}" deploy_test_backstage_customization_provider "${NAME_SPACE}" @@ -81,12 +81,36 @@ initiate_operator_deployments_osd_gcp() { } run_operator_runtime_config_change_tests() { - # Deploy `showcase-runtime` to run tests that require configuration changes at runtime + # Deploy `showcase-runtime` to run tests that require configuration changes at runtime. + # The runtime CRD (rhdh-start-runtime.yaml) uses an external PostgreSQL database + # (enableLocalDb: false) and requires postgres-crt and postgres-cred secrets. + + namespace::configure "${NAME_SPACE_POSTGRES_DB}" namespace::configure "${NAME_SPACE_RUNTIME}" + + # Set up the external PostgreSQL database (Crunchy Postgres) and create the postgres-cred secret + configure_external_postgres_db "${NAME_SPACE_RUNTIME}" + + # Create the postgres-crt secret from the Crunchy Postgres cluster CA certificate. + # The rhdh-start-runtime.yaml CRD mounts this as /opt/app-root/src/postgres-crt.pem + log::info "Creating postgres-crt secret in ${NAME_SPACE_RUNTIME} from Crunchy Postgres cluster certificate..." + oc get secret postgress-external-db-cluster-cert -n "${NAME_SPACE_POSTGRES_DB}" \ + -o jsonpath='{.data.ca\.crt}' | base64 --decode > /tmp/postgres-crt.pem + oc create secret generic postgres-crt \ + --from-file="postgres-crt.pem=/tmp/postgres-crt.pem" \ + --namespace="${NAME_SPACE_RUNTIME}" \ + --dry-run=client -o yaml | oc apply -f - + + # Update the RHDH_RUNTIME_URL in the postgres-cred secret + local runtime_url="https://backstage-${RELEASE_NAME}-${NAME_SPACE_RUNTIME}.${K8S_CLUSTER_ROUTER_BASE}" + local runtime_url_b64 + runtime_url_b64=$(echo -n "${runtime_url}" | base64 -w 0) + oc patch secret postgres-cred -n "${NAME_SPACE_RUNTIME}" \ + --type='json' -p="[{\"op\": \"replace\", \"path\": \"/data/RHDH_RUNTIME_URL\", \"value\": \"${runtime_url_b64}\"}]" || true + oc apply -f "$DIR/resources/postgres-db/dynamic-plugins-root-PVC.yaml" -n "${NAME_SPACE_RUNTIME}" config::create_app_config_map "$DIR/resources/postgres-db/rds-app-config.yaml" "${NAME_SPACE_RUNTIME}" deploy_rhdh_operator "${NAME_SPACE_RUNTIME}" "${DIR}/resources/rhdh-operator/rhdh-start-runtime.yaml" - local runtime_url="https://backstage-${RELEASE_NAME}-${NAME_SPACE_RUNTIME}.${K8S_CLUSTER_ROUTER_BASE}" testing::run_tests "${RELEASE_NAME}" "${NAME_SPACE_RUNTIME}" "${PW_PROJECT_SHOWCASE_RUNTIME}" "${runtime_url}" } diff --git a/.ibm/pipelines/utils.sh b/.ibm/pipelines/utils.sh index 67d7cdffb9..55888f1987 100755 --- a/.ibm/pipelines/utils.sh +++ b/.ibm/pipelines/utils.sh @@ -413,8 +413,15 @@ cluster_setup_ocp_operator() { k8s_wait::endpoint "${TEKTON_PIPELINES_WEBHOOK}" "openshift-pipelines" 1800 10 || return 1 operator::install_postgres_ocp - operator::install_serverless - operator::install_serverless_logic + + # Serverless operators are only needed for orchestrator workflows. + # Skip them on OSD-GCP and PR jobs where orchestrator is disabled. + if should_skip_orchestrator; then + log::warn "Skipping Serverless and Serverless Logic operator installation (orchestrator disabled for this job)" + else + operator::install_serverless + operator::install_serverless_logic + fi } cluster_setup_k8s_operator() { diff --git a/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml b/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml index 7ccddf74b4..e606d65df5 100644 --- a/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml +++ b/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml @@ -9,8 +9,8 @@ orchestrator: null global: dynamic: plugins: - # Disable orchestrator plugins for OSD-GCP - Official release (Backstage 1.42.5) - - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-orchestrator:bs_1.45.3__5.3.1!red-hat-developer-hub-backstage-plugin-orchestrator" + # Disable orchestrator plugins for OSD-GCP - Official release (Backstage 1.45.3) + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-orchestrator:bs_1.45.3__5.1.0!red-hat-developer-hub-backstage-plugin-orchestrator" disabled: true - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-orchestrator-backend:bs_1.45.3__8.3.0!red-hat-developer-hub-backstage-plugin-orchestrator-backend" disabled: true diff --git a/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml b/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml index f3dcb5f70b..eed13412d3 100644 --- a/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml +++ b/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml @@ -9,8 +9,8 @@ orchestrator: null global: dynamic: plugins: - # Disable orchestrator plugins for OSD-GCP - Official release (Backstage 1.42.5) - - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-orchestrator:bs_1.45.3__5.3.1!red-hat-developer-hub-backstage-plugin-orchestrator" + # Disable orchestrator plugins for OSD-GCP - Official release (Backstage 1.45.3) + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-orchestrator:bs_1.45.3__5.1.0!red-hat-developer-hub-backstage-plugin-orchestrator" disabled: true - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-orchestrator-backend:bs_1.45.3__8.3.0!red-hat-developer-hub-backstage-plugin-orchestrator-backend" disabled: true From a54fca588a35828666d419156332e40f8b5d5b48 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Wed, 18 Feb 2026 12:01:06 +0000 Subject: [PATCH 02/19] fix(ci): fix duplicate plugin crash in OSD-GCP operator deployments Signed-off-by: Fortune-Ndlovu --- .ibm/pipelines/lib/helm.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.ibm/pipelines/lib/helm.sh b/.ibm/pipelines/lib/helm.sh index 78b656ebd3..5513264ff8 100644 --- a/.ibm/pipelines/lib/helm.sh +++ b/.ibm/pipelines/lib/helm.sh @@ -50,10 +50,13 @@ helm::merge_values() { ' "${base_file}" "${diff_file}" > "${step_1_file}" # Step 2: Merge files, combining the .global.dynamic.plugins key - # Values from `diff_file` take precedence; plugins are merged and deduplicated by the .package field + # Values from `diff_file` take precedence; plugins are merged and deduplicated. + # For OCI packages (oci://registry:tag!path), deduplication strips the version tag + # so that packages differing only in version are treated as the same plugin. + # This prevents duplicate entries when diff files use different plugin versions than the base. yq eval-all ' select(fileIndex == 0) *+ select(fileIndex == 1) | - .global.dynamic.plugins |= (reverse | unique_by(.package) | reverse) + .global.dynamic.plugins |= (reverse | unique_by(.package | sub(":[^!]+!"; ":!")) | reverse) ' "${base_file}" "${diff_file}" > "${step_2_file}" # Step 3: Combine results from the previous steps and remove null values From 6ecf6b5a0b792bce414eb48cc5de5c31999c7d68 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Tue, 24 Feb 2026 16:18:56 +0000 Subject: [PATCH 03/19] fix(ci): strip CATALOG_INDEX_IMAGE for OSD-GCP operator deployments OSD-GCP clusters have unreliable connectivity to ghcr.io. The catalog index (CATALOG_INDEX_IMAGE) triggers ~30+ skopeo inspect calls to ghcr.io for auto-detection of OCI plugin paths, causing consistent dial tcp i/o timeouts that crash the install-dynamic-plugins init container (Init:CrashLoopBackOff). Strip CATALOG_INDEX_IMAGE from the Backstage CRs for OSD-GCP only. The init container will use built-in local defaults and only process explicitly-configured ConfigMap plugins (which have !plugin-path set, avoiding auto-detection). The catalog index is still fully tested by the regular OCP, AKS, EKS, and GKE operator nightly jobs. Ref: RHDHBUGS-1136 --- .ibm/pipelines/jobs/ocp-operator.sh | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.ibm/pipelines/jobs/ocp-operator.sh b/.ibm/pipelines/jobs/ocp-operator.sh index c635e69216..ef0500c5ab 100644 --- a/.ibm/pipelines/jobs/ocp-operator.sh +++ b/.ibm/pipelines/jobs/ocp-operator.sh @@ -61,7 +61,17 @@ initiate_operator_deployments_osd_gcp() { oc apply -f /tmp/configmap-dynamic-plugins.yaml -n "${NAME_SPACE}" deploy_redis_cache "${NAME_SPACE}" - deploy_rhdh_operator "${NAME_SPACE}" "${DIR}/resources/rhdh-operator/rhdh-start.yaml" + + # Strip CATALOG_INDEX_IMAGE from the Backstage CR for OSD-GCP. + # The catalog index triggers ~30+ skopeo inspect calls to ghcr.io for auto-detection + # of OCI plugin paths. OSD-GCP clusters have unreliable connectivity to ghcr.io, + # causing consistent dial tcp i/o timeouts that crash the install-dynamic-plugins init container. + # Without CATALOG_INDEX_IMAGE, the init container uses the built-in local defaults and only + # processes the explicitly-configured ConfigMap plugins (which have !plugin-path set). + local osd_gcp_showcase_cr="/tmp/rhdh-start-osd-gcp.yaml" + yq 'del(.spec.application.extraEnvs.envs[] | select(.name == "CATALOG_INDEX_IMAGE"))' \ + "${DIR}/resources/rhdh-operator/rhdh-start.yaml" > "$osd_gcp_showcase_cr" + deploy_rhdh_operator "${NAME_SPACE}" "$osd_gcp_showcase_cr" # Skip orchestrator plugins and workflows for OSD-GCP log::warn "Skipping orchestrator plugins and workflows deployment on OSD-GCP environment" @@ -78,7 +88,12 @@ initiate_operator_deployments_osd_gcp() { common::save_artifact "${NAME_SPACE_RBAC}" "/tmp/configmap-dynamic-plugins-rbac.yaml" oc apply -f /tmp/configmap-dynamic-plugins-rbac.yaml -n "${NAME_SPACE_RBAC}" - deploy_rhdh_operator "${NAME_SPACE_RBAC}" "${DIR}/resources/rhdh-operator/rhdh-start-rbac.yaml" + + # Strip CATALOG_INDEX_IMAGE from the RBAC Backstage CR for the same OSD-GCP ghcr.io reasons + local osd_gcp_rbac_cr="/tmp/rhdh-start-rbac-osd-gcp.yaml" + yq 'del(.spec.application.extraEnvs.envs[] | select(.name == "CATALOG_INDEX_IMAGE"))' \ + "${DIR}/resources/rhdh-operator/rhdh-start-rbac.yaml" > "$osd_gcp_rbac_cr" + deploy_rhdh_operator "${NAME_SPACE_RBAC}" "$osd_gcp_rbac_cr" # Skip orchestrator plugins and workflows for OSD-GCP RBAC log::warn "Skipping orchestrator plugins and workflows deployment on OSD-GCP RBAC environment" From 577f47b326a29c8d12176b65621074e6a6363ab2 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Wed, 25 Feb 2026 09:48:43 +0000 Subject: [PATCH 04/19] detect CATALOG_INDEX_IMAGE from the Backstage CRs for OSD-GCP Signed-off-by: Fortune-Ndlovu --- .ibm/pipelines/jobs/ocp-operator.sh | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/.ibm/pipelines/jobs/ocp-operator.sh b/.ibm/pipelines/jobs/ocp-operator.sh index ef0500c5ab..c635e69216 100644 --- a/.ibm/pipelines/jobs/ocp-operator.sh +++ b/.ibm/pipelines/jobs/ocp-operator.sh @@ -61,17 +61,7 @@ initiate_operator_deployments_osd_gcp() { oc apply -f /tmp/configmap-dynamic-plugins.yaml -n "${NAME_SPACE}" deploy_redis_cache "${NAME_SPACE}" - - # Strip CATALOG_INDEX_IMAGE from the Backstage CR for OSD-GCP. - # The catalog index triggers ~30+ skopeo inspect calls to ghcr.io for auto-detection - # of OCI plugin paths. OSD-GCP clusters have unreliable connectivity to ghcr.io, - # causing consistent dial tcp i/o timeouts that crash the install-dynamic-plugins init container. - # Without CATALOG_INDEX_IMAGE, the init container uses the built-in local defaults and only - # processes the explicitly-configured ConfigMap plugins (which have !plugin-path set). - local osd_gcp_showcase_cr="/tmp/rhdh-start-osd-gcp.yaml" - yq 'del(.spec.application.extraEnvs.envs[] | select(.name == "CATALOG_INDEX_IMAGE"))' \ - "${DIR}/resources/rhdh-operator/rhdh-start.yaml" > "$osd_gcp_showcase_cr" - deploy_rhdh_operator "${NAME_SPACE}" "$osd_gcp_showcase_cr" + deploy_rhdh_operator "${NAME_SPACE}" "${DIR}/resources/rhdh-operator/rhdh-start.yaml" # Skip orchestrator plugins and workflows for OSD-GCP log::warn "Skipping orchestrator plugins and workflows deployment on OSD-GCP environment" @@ -88,12 +78,7 @@ initiate_operator_deployments_osd_gcp() { common::save_artifact "${NAME_SPACE_RBAC}" "/tmp/configmap-dynamic-plugins-rbac.yaml" oc apply -f /tmp/configmap-dynamic-plugins-rbac.yaml -n "${NAME_SPACE_RBAC}" - - # Strip CATALOG_INDEX_IMAGE from the RBAC Backstage CR for the same OSD-GCP ghcr.io reasons - local osd_gcp_rbac_cr="/tmp/rhdh-start-rbac-osd-gcp.yaml" - yq 'del(.spec.application.extraEnvs.envs[] | select(.name == "CATALOG_INDEX_IMAGE"))' \ - "${DIR}/resources/rhdh-operator/rhdh-start-rbac.yaml" > "$osd_gcp_rbac_cr" - deploy_rhdh_operator "${NAME_SPACE_RBAC}" "$osd_gcp_rbac_cr" + deploy_rhdh_operator "${NAME_SPACE_RBAC}" "${DIR}/resources/rhdh-operator/rhdh-start-rbac.yaml" # Skip orchestrator plugins and workflows for OSD-GCP RBAC log::warn "Skipping orchestrator plugins and workflows deployment on OSD-GCP RBAC environment" From b2220025f528c534ff13b354543bd977ed253b29 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Mon, 2 Mar 2026 11:45:00 +0000 Subject: [PATCH 05/19] fix: test script to check if the file exists before copying and improve error logging Signed-off-by: Fortune-Ndlovu --- .ibm/pipelines/lib/testing.sh | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/.ibm/pipelines/lib/testing.sh b/.ibm/pipelines/lib/testing.sh index aff7492ca1..3e8aaa1c27 100644 --- a/.ibm/pipelines/lib/testing.sh +++ b/.ibm/pipelines/lib/testing.sh @@ -167,12 +167,13 @@ testing::check_backstage_running() { oc get pods -n "${namespace}" # Early crash detection: fail fast if RHDH pods are in CrashLoopBackOff + # Check for init container crashes first (they show as "Init:CrashLoopBackOff" in pod status) local crash_pods - crash_pods=$(oc get pods -n "${namespace}" -l "app.kubernetes.io/instance in (${release_name},redhat-developer-hub,developer-hub,${release_name}-postgresql)" \ - -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.status.phase}{" "}{range .status.containerStatuses[*]}{.state.waiting.reason}{end}{range .status.initContainerStatuses[*]}{.state.waiting.reason}{end}{"\n"}{end}' 2> /dev/null | grep -E "CrashLoopBackOff" || true) - # Also check by name pattern for postgresql pods that may have different labels + crash_pods=$(oc get pods -n "${namespace}" --no-headers 2> /dev/null | grep -E "(${release_name}|developer-hub|backstage-${release_name})" | grep -E "Init:CrashLoopBackOff|CrashLoopBackOff" || true) + # Also check using jsonpath for more detailed status if [[ -z "${crash_pods}" ]]; then - crash_pods=$(oc get pods -n "${namespace}" --no-headers 2> /dev/null | grep -E "(${release_name}|developer-hub|postgresql)" | grep -E "CrashLoopBackOff|Init:CrashLoopBackOff" || true) + crash_pods=$(oc get pods -n "${namespace}" -l "app.kubernetes.io/instance in (${release_name},redhat-developer-hub,developer-hub,${release_name}-postgresql)" \ + -o jsonpath='{range .items[*]}{.metadata.name}{" "}{range .status.initContainerStatuses[*]}{.state.waiting.reason}{" "}{.state.terminated.reason}{end}{range .status.containerStatuses[*]}{.state.waiting.reason}{" "}{.state.terminated.reason}{end}{"\n"}{end}' 2> /dev/null | grep -E "CrashLoopBackOff|Error" || true) fi if [[ -n "${crash_pods}" ]]; then @@ -183,10 +184,29 @@ testing::check_backstage_running() { log::error "Recent logs from deployment:" oc logs deployment/${release_name}-developer-hub -n "${namespace}" --tail=100 --all-containers=true 2> /dev/null \ || oc logs deployment/${release_name} -n "${namespace}" --tail=100 --all-containers=true 2> /dev/null || true + # Get init container logs from crashing pods + log::error "Init container logs from crashing pods:" + while IFS= read -r pod_line; do + if [[ -n "${pod_line}" ]]; then + pod_name=$(echo "${pod_line}" | awk '{print $1}') + if [[ -n "${pod_name}" ]]; then + log::error "Logs for init container 'install-dynamic-plugins' in pod ${pod_name}:" + oc logs "${pod_name}" -n "${namespace}" -c install-dynamic-plugins --tail=100 2> /dev/null || \ + log::warn "Could not retrieve init container logs for ${pod_name}" + fi + fi + done <<< "${crash_pods}" log::error "Recent events:" oc get events -n "${namespace}" --sort-by='.lastTimestamp' | tail -20 mkdir -p "${ARTIFACT_DIR}/${namespace}" +<<<<<<< HEAD cp -a "/tmp/${LOGFILE}" "${ARTIFACT_DIR}/${namespace}/" || true +======= + if [[ -f "/tmp/${LOGFILE}" ]]; then + cp -a "/tmp/${LOGFILE}" "${ARTIFACT_DIR}/${namespace}/" || true + fi + save_all_pod_logs "${namespace}" +>>>>>>> 5aba6da7 (fix: test script to check if the file exists before copying and improve error logging) return 1 fi @@ -197,7 +217,14 @@ testing::check_backstage_running() { log::error "Failed to reach Backstage at ${url} after ${max_attempts} attempts." oc get events -n "${namespace}" --sort-by='.lastTimestamp' | tail -10 mkdir -p "${ARTIFACT_DIR}/${namespace}" +<<<<<<< HEAD cp -a "/tmp/${LOGFILE}" "${ARTIFACT_DIR}/${namespace}/" || true +======= + if [[ -f "/tmp/${LOGFILE}" ]]; then + cp -a "/tmp/${LOGFILE}" "${ARTIFACT_DIR}/${namespace}/" || true + fi + save_all_pod_logs "${namespace}" +>>>>>>> 5aba6da7 (fix: test script to check if the file exists before copying and improve error logging) return 1 } From f637d90abc9662068e5af97507d2bd5faa105ec5 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Mon, 2 Mar 2026 12:13:18 +0000 Subject: [PATCH 06/19] fix testing.sh Signed-off-by: Fortune-Ndlovu --- .ibm/pipelines/lib/testing.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ibm/pipelines/lib/testing.sh b/.ibm/pipelines/lib/testing.sh index 3e8aaa1c27..55038af63b 100644 --- a/.ibm/pipelines/lib/testing.sh +++ b/.ibm/pipelines/lib/testing.sh @@ -351,4 +351,4 @@ testing::check_upgrade_and_test() { save_overall_result 1 fi return 0 -} +} \ No newline at end of file From 0c89352bb59f08cd7b7ef1bd68bdb402ba205072 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Mon, 2 Mar 2026 12:14:43 +0000 Subject: [PATCH 07/19] accept incoming changes to testing.sh Signed-off-by: Fortune-Ndlovu --- .ibm/pipelines/lib/testing.sh | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.ibm/pipelines/lib/testing.sh b/.ibm/pipelines/lib/testing.sh index 55038af63b..a0125c4693 100644 --- a/.ibm/pipelines/lib/testing.sh +++ b/.ibm/pipelines/lib/testing.sh @@ -199,14 +199,10 @@ testing::check_backstage_running() { log::error "Recent events:" oc get events -n "${namespace}" --sort-by='.lastTimestamp' | tail -20 mkdir -p "${ARTIFACT_DIR}/${namespace}" -<<<<<<< HEAD - cp -a "/tmp/${LOGFILE}" "${ARTIFACT_DIR}/${namespace}/" || true -======= if [[ -f "/tmp/${LOGFILE}" ]]; then cp -a "/tmp/${LOGFILE}" "${ARTIFACT_DIR}/${namespace}/" || true fi save_all_pod_logs "${namespace}" ->>>>>>> 5aba6da7 (fix: test script to check if the file exists before copying and improve error logging) return 1 fi @@ -217,14 +213,10 @@ testing::check_backstage_running() { log::error "Failed to reach Backstage at ${url} after ${max_attempts} attempts." oc get events -n "${namespace}" --sort-by='.lastTimestamp' | tail -10 mkdir -p "${ARTIFACT_DIR}/${namespace}" -<<<<<<< HEAD - cp -a "/tmp/${LOGFILE}" "${ARTIFACT_DIR}/${namespace}/" || true -======= if [[ -f "/tmp/${LOGFILE}" ]]; then cp -a "/tmp/${LOGFILE}" "${ARTIFACT_DIR}/${namespace}/" || true fi save_all_pod_logs "${namespace}" ->>>>>>> 5aba6da7 (fix: test script to check if the file exists before copying and improve error logging) return 1 } From 8a2d8d786abd387680af20c2a49e73b03c185f2e Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Mon, 2 Mar 2026 12:26:04 +0000 Subject: [PATCH 08/19] Moved the || operator to the start of the next line instead of the end of the previous line. Signed-off-by: Fortune-Ndlovu --- .ibm/pipelines/lib/testing.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.ibm/pipelines/lib/testing.sh b/.ibm/pipelines/lib/testing.sh index a0125c4693..f4a5b166b5 100644 --- a/.ibm/pipelines/lib/testing.sh +++ b/.ibm/pipelines/lib/testing.sh @@ -191,8 +191,8 @@ testing::check_backstage_running() { pod_name=$(echo "${pod_line}" | awk '{print $1}') if [[ -n "${pod_name}" ]]; then log::error "Logs for init container 'install-dynamic-plugins' in pod ${pod_name}:" - oc logs "${pod_name}" -n "${namespace}" -c install-dynamic-plugins --tail=100 2> /dev/null || \ - log::warn "Could not retrieve init container logs for ${pod_name}" + oc logs "${pod_name}" -n "${namespace}" -c install-dynamic-plugins --tail=100 2> /dev/null \ + || log::warn "Could not retrieve init container logs for ${pod_name}" fi fi done <<< "${crash_pods}" @@ -343,4 +343,4 @@ testing::check_upgrade_and_test() { save_overall_result 1 fi return 0 -} \ No newline at end of file +} From 75808469dbf8ec8291b5a1fb94d149c33e2e8652 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Mon, 2 Mar 2026 12:29:36 +0000 Subject: [PATCH 09/19] ensure /tmp/ exists before processing it with ansi2html. Signed-off-by: Fortune-Ndlovu --- .ibm/pipelines/lib/testing.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.ibm/pipelines/lib/testing.sh b/.ibm/pipelines/lib/testing.sh index f4a5b166b5..464af0e804 100644 --- a/.ibm/pipelines/lib/testing.sh +++ b/.ibm/pipelines/lib/testing.sh @@ -95,8 +95,10 @@ testing::run_tests() { fi cp -a "${e2e_tests_dir}/screenshots/"* "${ARTIFACT_DIR}/${artifacts_subdir}/attachments/screenshots/" || true - ansi2html < "/tmp/${LOGFILE}" > "/tmp/${LOGFILE}.html" - cp -a "/tmp/${LOGFILE}.html" "${ARTIFACT_DIR}/${artifacts_subdir}" || true + if [[ -f "/tmp/${LOGFILE}" ]]; then + ansi2html < "/tmp/${LOGFILE}" > "/tmp/${LOGFILE}.html" + cp -a "/tmp/${LOGFILE}.html" "${ARTIFACT_DIR}/${artifacts_subdir}" || true + fi cp -a "${e2e_tests_dir}/playwright-report/"* "${ARTIFACT_DIR}/${artifacts_subdir}" || true echo "Playwright project '${playwright_project}' in namespace '${namespace}' (artifacts: ${artifacts_subdir}) RESULT: ${test_result}" From ce2c6cf27823c4cfd03dc88eced67574b6b818e0 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Mon, 2 Mar 2026 16:02:19 +0000 Subject: [PATCH 10/19] Disabled the three failing plugins in both OSD-GCP diff files Signed-off-by: Fortune-Ndlovu --- .../value_files/diff-values_showcase-rbac_OSD-GCP.yaml | 8 ++++++++ .../value_files/diff-values_showcase_OSD-GCP.yaml | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml b/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml index b4643fbd95..f724496a66 100644 --- a/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml +++ b/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml @@ -18,3 +18,11 @@ global: disabled: true - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-orchestrator-form-widgets:bs_1.45.3__1.2.0!red-hat-developer-hub-backstage-plugin-orchestrator-form-widgets" disabled: true + # Disable ghcr.io plugins that require network access (OSD-GCP cannot reach ghcr.io) + # These plugins fail during auto-detection of plugin paths due to network timeouts + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-scaffolder-backend-module-quay:bs_1.45.3__2.14.0" + disabled: true + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-nexus-repository-manager:bs_1.45.3__1.19.4" + disabled: true + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-jenkins-backend:bs_1.45.3__0.22.0" + disabled: true diff --git a/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml b/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml index 5138173af1..a80e0698dc 100644 --- a/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml +++ b/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml @@ -18,3 +18,11 @@ global: disabled: true - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-orchestrator-form-widgets:bs_1.45.3__1.2.0!red-hat-developer-hub-backstage-plugin-orchestrator-form-widgets" disabled: true + # Disable ghcr.io plugins that require network access (OSD-GCP cannot reach ghcr.io) + # These plugins fail during auto-detection of plugin paths due to network timeouts + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-scaffolder-backend-module-quay:bs_1.45.3__2.14.0" + disabled: true + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-nexus-repository-manager:bs_1.45.3__1.19.4" + disabled: true + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-jenkins-backend:bs_1.45.3__0.22.0" + disabled: true From b303613974e6275c973c0c50d783c62189c9c90a Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Mon, 2 Mar 2026 21:43:53 +0000 Subject: [PATCH 11/19] fix plugins to remain enabled and testable, and the init container should no longer fail due to network timeouts during auto-detection Signed-off-by: Fortune-Ndlovu --- .ibm/pipelines/jobs/ocp-operator.sh | 8 ++ .ibm/pipelines/lib/config.sh | 87 +++++++++++++++++++ .../diff-values_showcase-rbac_OSD-GCP.yaml | 15 ++-- .../diff-values_showcase_OSD-GCP.yaml | 15 ++-- 4 files changed, 109 insertions(+), 16 deletions(-) diff --git a/.ibm/pipelines/jobs/ocp-operator.sh b/.ibm/pipelines/jobs/ocp-operator.sh index c635e69216..60cd9e8d11 100644 --- a/.ibm/pipelines/jobs/ocp-operator.sh +++ b/.ibm/pipelines/jobs/ocp-operator.sh @@ -60,6 +60,10 @@ initiate_operator_deployments_osd_gcp() { common::save_artifact "${NAME_SPACE}" "/tmp/configmap-dynamic-plugins.yaml" oc apply -f /tmp/configmap-dynamic-plugins.yaml -n "${NAME_SPACE}" + # Add explicit plugin paths for ghcr.io plugins to avoid network calls during auto-detection + # Patch the ConfigMap before deploying the operator so the init container reads the patched version + config::add_explicit_plugin_paths_osd_gcp "${NAME_SPACE}" "dynamic-plugins" + deploy_redis_cache "${NAME_SPACE}" deploy_rhdh_operator "${NAME_SPACE}" "${DIR}/resources/rhdh-operator/rhdh-start.yaml" @@ -78,6 +82,10 @@ initiate_operator_deployments_osd_gcp() { common::save_artifact "${NAME_SPACE_RBAC}" "/tmp/configmap-dynamic-plugins-rbac.yaml" oc apply -f /tmp/configmap-dynamic-plugins-rbac.yaml -n "${NAME_SPACE_RBAC}" + # Add explicit plugin paths for ghcr.io plugins to avoid network calls during auto-detection + # Patch the ConfigMap before deploying the operator so the init container reads the patched version + config::add_explicit_plugin_paths_osd_gcp "${NAME_SPACE_RBAC}" "dynamic-plugins" + deploy_rhdh_operator "${NAME_SPACE_RBAC}" "${DIR}/resources/rhdh-operator/rhdh-start-rbac.yaml" # Skip orchestrator plugins and workflows for OSD-GCP RBAC diff --git a/.ibm/pipelines/lib/config.sh b/.ibm/pipelines/lib/config.sh index 9978499bc5..6c3d8b0486 100644 --- a/.ibm/pipelines/lib/config.sh +++ b/.ibm/pipelines/lib/config.sh @@ -140,3 +140,90 @@ config::prepare_operator_app_config() { yq e -i '.permission.rbac.conditionalPoliciesFile = "./rbac/conditional-policies.yaml"' "${config_file}" return $? } + +# Add explicit plugin paths for ghcr.io plugins to avoid network calls during auto-detection +# This is needed for OSD-GCP where ghcr.io is not accessible during init container execution +# Args: +# $1 - namespace: Target namespace +# $2 - configmap_name: Name of the ConfigMap (default: dynamic-plugins) +# Returns: +# 0 - Success +config::add_explicit_plugin_paths_osd_gcp() { + local namespace=$1 + local configmap_name="${2:-dynamic-plugins}" + + if [[ -z "$namespace" ]]; then + log::error "Missing required parameter: namespace" + log::info "Usage: config::add_explicit_plugin_paths_osd_gcp [configmap_name]" + return 1 + fi + + log::info "Adding explicit plugin paths for ghcr.io plugins in ConfigMap ${configmap_name} (OSD-GCP cannot reach ghcr.io for auto-detection)" + + # Map of plugin packages to their explicit plugin paths (to avoid network calls for auto-detection) + # Format: "package:version" -> "plugin-path" + declare -A plugin_paths=( + ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-scaffolder-backend-module-quay:bs_1.45.3__2.14.0"]="backstage-community-plugin-scaffolder-backend-module-quay" + ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-nexus-repository-manager:bs_1.45.3__1.19.4"]="backstage-community-plugin-nexus-repository-manager" + ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-jenkins-backend:bs_1.45.3__0.22.0"]="backstage-community-plugin-jenkins-backend" + ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-scaffolder-backend-module-bitbucket-cloud:bs_1.45.3__0.2.15"]="backstage-plugin-scaffolder-backend-module-bitbucket-cloud" + ) + + # Get current ConfigMap content + local current_yaml + current_yaml=$(oc get cm "${configmap_name}" -n "${namespace}" -o jsonpath='{.data.dynamic-plugins\.yaml}' 2>/dev/null) + + if [[ -z "$current_yaml" ]]; then + log::warn "ConfigMap ${configmap_name} not found or has no dynamic-plugins.yaml data in namespace ${namespace}" + return 0 + fi + + # Create a temporary file with the current YAML + local temp_file + temp_file=$(mktemp) + echo "$current_yaml" > "$temp_file" + + # Update each plugin to include explicit plugin path + local updated=false + for plugin_package in "${!plugin_paths[@]}"; do + local plugin_path="${plugin_paths[$plugin_package]}" + local package_with_path="${plugin_package}!${plugin_path}" + + # Check if plugin exists without explicit path + local plugin_without_path + plugin_without_path=$(yq eval ".plugins[] | select(.package == \"${plugin_package}\")" "$temp_file" 2>/dev/null) + + if [[ -n "$plugin_without_path" ]]; then + # Plugin exists without explicit path, update it to include the path + yq eval -i "(.plugins[] | select(.package == \"${plugin_package}\")).package = \"${package_with_path}\"" "$temp_file" + log::info "Added explicit plugin path for: ${plugin_package} -> ${plugin_path}" + updated=true + else + # Check if plugin exists with explicit path already + local plugin_with_path + plugin_with_path=$(yq eval ".plugins[] | select(.package == \"${package_with_path}\")" "$temp_file" 2>/dev/null) + + if [[ -z "$plugin_with_path" ]]; then + # Plugin doesn't exist at all, add it with explicit path (preserving disabled state if it was in catalog index) + # We'll add it as enabled by default, but it might be overridden by catalog index entries + yq eval -i ".plugins += [{\"package\": \"${package_with_path}\"}]" "$temp_file" + log::info "Added plugin with explicit path: ${package_with_path}" + updated=true + fi + fi + done + + if [[ "$updated" == "true" ]]; then + # Update the ConfigMap with the modified YAML + local updated_yaml + updated_yaml=$(cat "$temp_file") + oc patch cm "${configmap_name}" -n "${namespace}" --type merge \ + -p "{\"data\":{\"dynamic-plugins.yaml\":$(echo "$updated_yaml" | jq -Rs .)}}" + log::success "Updated ConfigMap ${configmap_name} to include explicit plugin paths for ghcr.io plugins" + else + log::info "No updates needed for ConfigMap ${configmap_name}" + fi + + rm -f "$temp_file" + return 0 +} diff --git a/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml b/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml index f724496a66..014ea856e9 100644 --- a/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml +++ b/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml @@ -18,11 +18,10 @@ global: disabled: true - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-orchestrator-form-widgets:bs_1.45.3__1.2.0!red-hat-developer-hub-backstage-plugin-orchestrator-form-widgets" disabled: true - # Disable ghcr.io plugins that require network access (OSD-GCP cannot reach ghcr.io) - # These plugins fail during auto-detection of plugin paths due to network timeouts - - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-scaffolder-backend-module-quay:bs_1.45.3__2.14.0" - disabled: true - - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-nexus-repository-manager:bs_1.45.3__1.19.4" - disabled: true - - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-jenkins-backend:bs_1.45.3__0.22.0" - disabled: true + # Add explicit plugin paths for ghcr.io plugins to avoid network calls during auto-detection + # OSD-GCP cannot reach ghcr.io during init container execution, so we provide explicit paths + # This allows plugins to remain enabled and testable while avoiding network timeout errors + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-scaffolder-backend-module-quay:bs_1.45.3__2.14.0!backstage-community-plugin-scaffolder-backend-module-quay" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-nexus-repository-manager:bs_1.45.3__1.19.4!backstage-community-plugin-nexus-repository-manager" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-jenkins-backend:bs_1.45.3__0.22.0!backstage-community-plugin-jenkins-backend" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-scaffolder-backend-module-bitbucket-cloud:bs_1.45.3__0.2.15!backstage-plugin-scaffolder-backend-module-bitbucket-cloud" \ No newline at end of file diff --git a/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml b/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml index a80e0698dc..b07d3cbbb3 100644 --- a/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml +++ b/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml @@ -18,11 +18,10 @@ global: disabled: true - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-orchestrator-form-widgets:bs_1.45.3__1.2.0!red-hat-developer-hub-backstage-plugin-orchestrator-form-widgets" disabled: true - # Disable ghcr.io plugins that require network access (OSD-GCP cannot reach ghcr.io) - # These plugins fail during auto-detection of plugin paths due to network timeouts - - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-scaffolder-backend-module-quay:bs_1.45.3__2.14.0" - disabled: true - - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-nexus-repository-manager:bs_1.45.3__1.19.4" - disabled: true - - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-jenkins-backend:bs_1.45.3__0.22.0" - disabled: true + # Add explicit plugin paths for ghcr.io plugins to avoid network calls during auto-detection + # OSD-GCP cannot reach ghcr.io during init container execution, so we provide explicit paths + # This allows plugins to remain enabled and testable while avoiding network timeout errors + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-scaffolder-backend-module-quay:bs_1.45.3__2.14.0!backstage-community-plugin-scaffolder-backend-module-quay" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-nexus-repository-manager:bs_1.45.3__1.19.4!backstage-community-plugin-nexus-repository-manager" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-jenkins-backend:bs_1.45.3__0.22.0!backstage-community-plugin-jenkins-backend" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-scaffolder-backend-module-bitbucket-cloud:bs_1.45.3__0.2.15!backstage-plugin-scaffolder-backend-module-bitbucket-cloud" \ No newline at end of file From f3957aaca34bf89cff70fdf475a3b19018a21242 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Mon, 2 Mar 2026 22:02:50 +0000 Subject: [PATCH 12/19] run ./.ibm yarn prettier:fix Signed-off-by: Fortune-Ndlovu --- .ibm/pipelines/lib/config.sh | 6 +++--- .../value_files/diff-values_showcase-rbac_OSD-GCP.yaml | 2 +- .../pipelines/value_files/diff-values_showcase_OSD-GCP.yaml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.ibm/pipelines/lib/config.sh b/.ibm/pipelines/lib/config.sh index 6c3d8b0486..7641b272c3 100644 --- a/.ibm/pipelines/lib/config.sh +++ b/.ibm/pipelines/lib/config.sh @@ -171,7 +171,7 @@ config::add_explicit_plugin_paths_osd_gcp() { # Get current ConfigMap content local current_yaml - current_yaml=$(oc get cm "${configmap_name}" -n "${namespace}" -o jsonpath='{.data.dynamic-plugins\.yaml}' 2>/dev/null) + current_yaml=$(oc get cm "${configmap_name}" -n "${namespace}" -o jsonpath='{.data.dynamic-plugins\.yaml}' 2> /dev/null) if [[ -z "$current_yaml" ]]; then log::warn "ConfigMap ${configmap_name} not found or has no dynamic-plugins.yaml data in namespace ${namespace}" @@ -191,7 +191,7 @@ config::add_explicit_plugin_paths_osd_gcp() { # Check if plugin exists without explicit path local plugin_without_path - plugin_without_path=$(yq eval ".plugins[] | select(.package == \"${plugin_package}\")" "$temp_file" 2>/dev/null) + plugin_without_path=$(yq eval ".plugins[] | select(.package == \"${plugin_package}\")" "$temp_file" 2> /dev/null) if [[ -n "$plugin_without_path" ]]; then # Plugin exists without explicit path, update it to include the path @@ -201,7 +201,7 @@ config::add_explicit_plugin_paths_osd_gcp() { else # Check if plugin exists with explicit path already local plugin_with_path - plugin_with_path=$(yq eval ".plugins[] | select(.package == \"${package_with_path}\")" "$temp_file" 2>/dev/null) + plugin_with_path=$(yq eval ".plugins[] | select(.package == \"${package_with_path}\")" "$temp_file" 2> /dev/null) if [[ -z "$plugin_with_path" ]]; then # Plugin doesn't exist at all, add it with explicit path (preserving disabled state if it was in catalog index) diff --git a/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml b/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml index 014ea856e9..fa902cdee4 100644 --- a/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml +++ b/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml @@ -24,4 +24,4 @@ global: - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-scaffolder-backend-module-quay:bs_1.45.3__2.14.0!backstage-community-plugin-scaffolder-backend-module-quay" - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-nexus-repository-manager:bs_1.45.3__1.19.4!backstage-community-plugin-nexus-repository-manager" - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-jenkins-backend:bs_1.45.3__0.22.0!backstage-community-plugin-jenkins-backend" - - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-scaffolder-backend-module-bitbucket-cloud:bs_1.45.3__0.2.15!backstage-plugin-scaffolder-backend-module-bitbucket-cloud" \ No newline at end of file + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-scaffolder-backend-module-bitbucket-cloud:bs_1.45.3__0.2.15!backstage-plugin-scaffolder-backend-module-bitbucket-cloud" diff --git a/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml b/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml index b07d3cbbb3..39f7c095a2 100644 --- a/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml +++ b/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml @@ -24,4 +24,4 @@ global: - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-scaffolder-backend-module-quay:bs_1.45.3__2.14.0!backstage-community-plugin-scaffolder-backend-module-quay" - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-nexus-repository-manager:bs_1.45.3__1.19.4!backstage-community-plugin-nexus-repository-manager" - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-jenkins-backend:bs_1.45.3__0.22.0!backstage-community-plugin-jenkins-backend" - - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-scaffolder-backend-module-bitbucket-cloud:bs_1.45.3__0.2.15!backstage-plugin-scaffolder-backend-module-bitbucket-cloud" \ No newline at end of file + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-scaffolder-backend-module-bitbucket-cloud:bs_1.45.3__0.2.15!backstage-plugin-scaffolder-backend-module-bitbucket-cloud" From 691863a0c3ac9b3113d234df833cef5e9e3e0343 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Tue, 3 Mar 2026 10:41:44 +0000 Subject: [PATCH 13/19] add explicit paths --- .ibm/pipelines/lib/config.sh | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.ibm/pipelines/lib/config.sh b/.ibm/pipelines/lib/config.sh index 7641b272c3..76ede26d47 100644 --- a/.ibm/pipelines/lib/config.sh +++ b/.ibm/pipelines/lib/config.sh @@ -189,7 +189,7 @@ config::add_explicit_plugin_paths_osd_gcp() { local plugin_path="${plugin_paths[$plugin_package]}" local package_with_path="${plugin_package}!${plugin_path}" - # Check if plugin exists without explicit path + # Check if plugin exists without explicit path in the main plugins list local plugin_without_path plugin_without_path=$(yq eval ".plugins[] | select(.package == \"${plugin_package}\")" "$temp_file" 2> /dev/null) @@ -199,15 +199,20 @@ config::add_explicit_plugin_paths_osd_gcp() { log::info "Added explicit plugin path for: ${plugin_package} -> ${plugin_path}" updated=true else - # Check if plugin exists with explicit path already + # Check if plugin exists with explicit path already in the main plugins list local plugin_with_path plugin_with_path=$(yq eval ".plugins[] | select(.package == \"${package_with_path}\")" "$temp_file" 2> /dev/null) if [[ -z "$plugin_with_path" ]]; then - # Plugin doesn't exist at all, add it with explicit path (preserving disabled state if it was in catalog index) - # We'll add it as enabled by default, but it might be overridden by catalog index entries + # Plugin doesn't exist in main plugins list, add it with explicit path + # This ensures the plugin with explicit path is processed before catalog index plugins, + # allowing it to override catalog index entries that don't have explicit paths + # Initialize plugins array if it doesn't exist + if ! yq eval '.plugins' "$temp_file" > /dev/null 2>&1; then + yq eval -i '.plugins = []' "$temp_file" + fi yq eval -i ".plugins += [{\"package\": \"${package_with_path}\"}]" "$temp_file" - log::info "Added plugin with explicit path: ${package_with_path}" + log::info "Added plugin with explicit path to override catalog index: ${package_with_path}" updated=true fi fi From 8470f3e7087d4fd888a05767b3873e8c6f5e3115 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Tue, 3 Mar 2026 11:58:12 +0000 Subject: [PATCH 14/19] resolve the CI failure for the specific plugins that were failing. --- .ibm/pipelines/lib/config.sh | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/.ibm/pipelines/lib/config.sh b/.ibm/pipelines/lib/config.sh index 76ede26d47..7e4f69d983 100644 --- a/.ibm/pipelines/lib/config.sh +++ b/.ibm/pipelines/lib/config.sh @@ -162,11 +162,15 @@ config::add_explicit_plugin_paths_osd_gcp() { # Map of plugin packages to their explicit plugin paths (to avoid network calls for auto-detection) # Format: "package:version" -> "plugin-path" + # Note: For plugins with version patterns, we match on the base image path (without version) declare -A plugin_paths=( ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-scaffolder-backend-module-quay:bs_1.45.3__2.14.0"]="backstage-community-plugin-scaffolder-backend-module-quay" ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-nexus-repository-manager:bs_1.45.3__1.19.4"]="backstage-community-plugin-nexus-repository-manager" ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-jenkins-backend:bs_1.45.3__0.22.0"]="backstage-community-plugin-jenkins-backend" ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-scaffolder-backend-module-bitbucket-cloud:bs_1.45.3__0.2.15"]="backstage-plugin-scaffolder-backend-module-bitbucket-cloud" + ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-catalog-backend-module-bitbucket-cloud:bs_1.45.3__0.5.5"]="backstage-plugin-catalog-backend-module-bitbucket-cloud" + # Also include the older version that might be in value files + ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-scaffolder-backend-module-bitbucket-cloud:bs_1.45.3__0.2.15"]="backstage-plugin-scaffolder-backend-module-bitbucket-cloud" ) # Get current ConfigMap content @@ -183,6 +187,14 @@ config::add_explicit_plugin_paths_osd_gcp() { temp_file=$(mktemp) echo "$current_yaml" > "$temp_file" + # Helper function to extract plugin path from image name + # For ghcr.io plugins, the path is typically the last component before the tag + extract_plugin_path() { + local package="$1" + # Remove oci:// prefix and extract the last path component before : or @ + echo "${package}" | sed -E 's|^oci://ghcr.io/[^/]+/[^/]+/([^:@]+).*|\1|' + } + # Update each plugin to include explicit plugin path local updated=false for plugin_package in "${!plugin_paths[@]}"; do @@ -218,6 +230,46 @@ config::add_explicit_plugin_paths_osd_gcp() { fi done + # Also add any ghcr.io plugins from the value files that might not be in our explicit list + # Extract all ghcr.io plugins from the ConfigMap and ensure they have explicit paths + local all_ghcr_plugins + all_ghcr_plugins=$(yq eval '.plugins[] | select(.package | startswith("oci://ghcr.io")) | .package' "$temp_file" 2> /dev/null || true) + + if [[ -n "$all_ghcr_plugins" ]]; then + while IFS= read -r plugin_package; do + [[ -z "$plugin_package" ]] && continue + + # Skip if already has explicit path (!) + if [[ "$plugin_package" == *"!"* ]]; then + continue + fi + + # Check if this plugin is already in our explicit list + local found=false + for known_package in "${!plugin_paths[@]}"; do + # Compare base image path (without version) + local base_known="${known_package%%:*}" + local base_plugin="${plugin_package%%:*}" + if [[ "$base_known" == "$base_plugin" ]]; then + found=true + break + fi + done + + # If not in our list, infer the plugin path from the image name + if [[ "$found" == "false" ]]; then + local inferred_path + inferred_path=$(extract_plugin_path "$plugin_package") + local package_with_inferred_path="${plugin_package}!${inferred_path}" + + # Update the plugin to include the inferred path + yq eval -i "(.plugins[] | select(.package == \"${plugin_package}\")).package = \"${package_with_inferred_path}\"" "$temp_file" + log::info "Added inferred plugin path for: ${plugin_package} -> ${inferred_path}" + updated=true + fi + done <<< "$all_ghcr_plugins" + fi + if [[ "$updated" == "true" ]]; then # Update the ConfigMap with the modified YAML local updated_yaml From 058ca6b051390bfb0c7121ee14cdde536baae920 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Tue, 3 Mar 2026 12:17:40 +0000 Subject: [PATCH 15/19] yarn prettier:fix --- .ibm/pipelines/lib/config.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.ibm/pipelines/lib/config.sh b/.ibm/pipelines/lib/config.sh index 7e4f69d983..54c652d801 100644 --- a/.ibm/pipelines/lib/config.sh +++ b/.ibm/pipelines/lib/config.sh @@ -234,16 +234,16 @@ config::add_explicit_plugin_paths_osd_gcp() { # Extract all ghcr.io plugins from the ConfigMap and ensure they have explicit paths local all_ghcr_plugins all_ghcr_plugins=$(yq eval '.plugins[] | select(.package | startswith("oci://ghcr.io")) | .package' "$temp_file" 2> /dev/null || true) - + if [[ -n "$all_ghcr_plugins" ]]; then while IFS= read -r plugin_package; do [[ -z "$plugin_package" ]] && continue - + # Skip if already has explicit path (!) if [[ "$plugin_package" == *"!"* ]]; then continue fi - + # Check if this plugin is already in our explicit list local found=false for known_package in "${!plugin_paths[@]}"; do @@ -255,13 +255,13 @@ config::add_explicit_plugin_paths_osd_gcp() { break fi done - + # If not in our list, infer the plugin path from the image name if [[ "$found" == "false" ]]; then local inferred_path inferred_path=$(extract_plugin_path "$plugin_package") local package_with_inferred_path="${plugin_package}!${inferred_path}" - + # Update the plugin to include the inferred path yq eval -i "(.plugins[] | select(.package == \"${plugin_package}\")).package = \"${package_with_inferred_path}\"" "$temp_file" log::info "Added inferred plugin path for: ${plugin_package} -> ${inferred_path}" From 3dcd4c9ca524a26e1d2652c3cef54a98f4f54de0 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Tue, 3 Mar 2026 14:04:18 +0000 Subject: [PATCH 16/19] update --- .ibm/pipelines/lib/config.sh | 121 ++++++++++++++++-- .../diff-values_showcase-rbac_OSD-GCP.yaml | 6 + .../diff-values_showcase_OSD-GCP.yaml | 6 + 3 files changed, 123 insertions(+), 10 deletions(-) diff --git a/.ibm/pipelines/lib/config.sh b/.ibm/pipelines/lib/config.sh index 54c652d801..a6ca09bcf9 100644 --- a/.ibm/pipelines/lib/config.sh +++ b/.ibm/pipelines/lib/config.sh @@ -162,15 +162,20 @@ config::add_explicit_plugin_paths_osd_gcp() { # Map of plugin packages to their explicit plugin paths (to avoid network calls for auto-detection) # Format: "package:version" -> "plugin-path" - # Note: For plugins with version patterns, we match on the base image path (without version) + # This list includes all known ghcr.io plugins that might be in the catalog index + # The plugin path is typically the last component of the image path declare -A plugin_paths=( ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-scaffolder-backend-module-quay:bs_1.45.3__2.14.0"]="backstage-community-plugin-scaffolder-backend-module-quay" ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-nexus-repository-manager:bs_1.45.3__1.19.4"]="backstage-community-plugin-nexus-repository-manager" ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-jenkins-backend:bs_1.45.3__0.22.0"]="backstage-community-plugin-jenkins-backend" ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-scaffolder-backend-module-bitbucket-cloud:bs_1.45.3__0.2.15"]="backstage-plugin-scaffolder-backend-module-bitbucket-cloud" ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-catalog-backend-module-bitbucket-cloud:bs_1.45.3__0.5.5"]="backstage-plugin-catalog-backend-module-bitbucket-cloud" - # Also include the older version that might be in value files - ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-scaffolder-backend-module-bitbucket-cloud:bs_1.45.3__0.2.15"]="backstage-plugin-scaffolder-backend-module-bitbucket-cloud" + # Additional ghcr.io plugins that might be in the catalog index + ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-azure-devops-backend:bs_1.45.3__0.23.0"]="backstage-community-plugin-azure-devops-backend" + ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-azure-devops:bs_1.45.3__0.23.0"]="backstage-community-plugin-azure-devops" + ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-3scale-backend:bs_1.45.3__3.10.0"]="backstage-community-plugin-3scale-backend" + ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-argocd-backend:bs_1.45.3__1.0.2"]="backstage-community-plugin-argocd-backend" + ["oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-argocd:bs_1.45.3__2.4.3"]="backstage-community-plugin-argocd" ) # Get current ConfigMap content @@ -195,8 +200,108 @@ config::add_explicit_plugin_paths_osd_gcp() { echo "${package}" | sed -E 's|^oci://ghcr.io/[^/]+/[^/]+/([^:@]+).*|\1|' } + # Extract catalog index and add all ghcr.io plugins from it to the ConfigMap + # This ensures all catalog index plugins have explicit paths before the init container processes them + local catalog_index_image="quay.io/rhdh/plugin-catalog-index:1.10" + local catalog_index_temp_dir + catalog_index_temp_dir=$(mktemp -d) + trap "rm -rf ${catalog_index_temp_dir}" EXIT + + log::info "Extracting catalog index ${catalog_index_image} to find all ghcr.io plugins" + + if command -v skopeo > /dev/null 2>&1 && command -v yq > /dev/null 2>&1; then + local catalog_index_local_dir="${catalog_index_temp_dir}/catalog-index-oci" + mkdir -p "${catalog_index_local_dir}" + + # Try to extract the catalog index image (may fail if network is restricted, but that's okay) + if skopeo copy --override-os=linux --override-arch=amd64 "docker://${catalog_index_image}" "dir:${catalog_index_local_dir}" > /dev/null 2>&1; then + log::info "Successfully extracted catalog index image" + + # Extract the dynamic-plugins.default.yaml file + local manifest_path="${catalog_index_local_dir}/manifest.json" + if [[ -f "$manifest_path" ]]; then + # Extract layers to find the YAML file + local layer_digest + layer_digest=$(jq -r '.layers[0].digest' "$manifest_path" 2> /dev/null || echo "") + if [[ -n "$layer_digest" && "$layer_digest" != "null" ]]; then + local layer_file="${catalog_index_local_dir}/${layer_digest#sha256:}" + if [[ -f "$layer_file" ]]; then + # Extract the layer tarball + local catalog_yaml_dir="${catalog_index_temp_dir}/catalog-yaml" + mkdir -p "${catalog_yaml_dir}" + tar -xf "${layer_file}" -C "${catalog_yaml_dir}" 2> /dev/null || true + + local catalog_plugins_file="${catalog_yaml_dir}/dynamic-plugins.default.yaml" + if [[ -f "$catalog_plugins_file" ]]; then + log::info "Found catalog index plugins file, extracting ghcr.io plugins" + + # Extract all ghcr.io plugins from the catalog index + local catalog_ghcr_plugins + catalog_ghcr_plugins=$(yq eval '.plugins[] | select(.package | startswith("oci://ghcr.io")) | .package' "$catalog_plugins_file" 2> /dev/null || true) + + if [[ -n "$catalog_ghcr_plugins" ]]; then + while IFS= read -r catalog_plugin; do + [[ -z "$catalog_plugin" ]] && continue + + # Skip if already has explicit path + if [[ "$catalog_plugin" == *"!"* ]]; then + continue + fi + + # Infer plugin path from image name + local inferred_path + inferred_path=$(extract_plugin_path "$catalog_plugin") + local catalog_plugin_with_path="${catalog_plugin}!${inferred_path}" + + # Check if this plugin is already in our explicit list or ConfigMap + local already_added=false + for known_package in "${!plugin_paths[@]}"; do + local base_known="${known_package%%:*}" + local base_catalog="${catalog_plugin%%:*}" + if [[ "$base_known" == "$base_catalog" ]]; then + already_added=true + break + fi + done + + # Also check if it's already in the ConfigMap + if [[ "$already_added" == "false" ]]; then + local existing_in_cm + existing_in_cm=$(yq eval ".plugins[] | select(.package == \"${catalog_plugin_with_path}\" or .package == \"${catalog_plugin}\")" "$temp_file" 2> /dev/null || true) + if [[ -n "$existing_in_cm" ]]; then + already_added=true + fi + fi + + # Add to plugin_paths map if not already there + if [[ "$already_added" == "false" ]]; then + plugin_paths["${catalog_plugin}"]="${inferred_path}" + log::info "Found ghcr.io plugin in catalog index: ${catalog_plugin} -> ${inferred_path}" + fi + done <<< "$catalog_ghcr_plugins" + fi + fi + fi + fi + fi + else + log::warn "Could not extract catalog index image (network may be restricted), using known plugin list only" + fi + else + log::warn "skopeo or yq not available, using known plugin list only" + fi + # Update each plugin to include explicit plugin path + # CRITICAL: We MUST add ALL ghcr.io plugins to the main plugins list with explicit paths + # because the Python script processes includes (catalog index) FIRST, and if a plugin + # without an explicit path is encountered, it fails before checking the main plugins list local updated=false + + # Initialize plugins array if it doesn't exist + if ! yq eval '.plugins' "$temp_file" > /dev/null 2>&1; then + yq eval -i '.plugins = []' "$temp_file" + fi + for plugin_package in "${!plugin_paths[@]}"; do local plugin_path="${plugin_paths[$plugin_package]}" local package_with_path="${plugin_package}!${plugin_path}" @@ -216,13 +321,9 @@ config::add_explicit_plugin_paths_osd_gcp() { plugin_with_path=$(yq eval ".plugins[] | select(.package == \"${package_with_path}\")" "$temp_file" 2> /dev/null) if [[ -z "$plugin_with_path" ]]; then - # Plugin doesn't exist in main plugins list, add it with explicit path - # This ensures the plugin with explicit path is processed before catalog index plugins, - # allowing it to override catalog index entries that don't have explicit paths - # Initialize plugins array if it doesn't exist - if ! yq eval '.plugins' "$temp_file" > /dev/null 2>&1; then - yq eval -i '.plugins = []' "$temp_file" - fi + # Plugin doesn't exist in main plugins list - ALWAYS add it with explicit path + # This is critical: we must add ALL ghcr.io plugins to the main plugins list + # so they're available when the script processes includes, preventing auto-detection failures yq eval -i ".plugins += [{\"package\": \"${package_with_path}\"}]" "$temp_file" log::info "Added plugin with explicit path to override catalog index: ${package_with_path}" updated=true diff --git a/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml b/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml index fa902cdee4..026e82c7b2 100644 --- a/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml +++ b/.ibm/pipelines/value_files/diff-values_showcase-rbac_OSD-GCP.yaml @@ -25,3 +25,9 @@ global: - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-nexus-repository-manager:bs_1.45.3__1.19.4!backstage-community-plugin-nexus-repository-manager" - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-jenkins-backend:bs_1.45.3__0.22.0!backstage-community-plugin-jenkins-backend" - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-scaffolder-backend-module-bitbucket-cloud:bs_1.45.3__0.2.15!backstage-plugin-scaffolder-backend-module-bitbucket-cloud" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-catalog-backend-module-bitbucket-cloud:bs_1.45.3__0.5.5!backstage-plugin-catalog-backend-module-bitbucket-cloud" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-azure-devops-backend:bs_1.45.3__0.23.0!backstage-community-plugin-azure-devops-backend" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-azure-devops:bs_1.45.3__0.23.0!backstage-community-plugin-azure-devops" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-3scale-backend:bs_1.45.3__3.10.0!backstage-community-plugin-3scale-backend" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-argocd-backend:bs_1.45.3__1.0.2!backstage-community-plugin-argocd-backend" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-argocd:bs_1.45.3__2.4.3!backstage-community-plugin-argocd" diff --git a/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml b/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml index 39f7c095a2..fff38c3c7e 100644 --- a/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml +++ b/.ibm/pipelines/value_files/diff-values_showcase_OSD-GCP.yaml @@ -25,3 +25,9 @@ global: - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-nexus-repository-manager:bs_1.45.3__1.19.4!backstage-community-plugin-nexus-repository-manager" - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-jenkins-backend:bs_1.45.3__0.22.0!backstage-community-plugin-jenkins-backend" - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-scaffolder-backend-module-bitbucket-cloud:bs_1.45.3__0.2.15!backstage-plugin-scaffolder-backend-module-bitbucket-cloud" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-catalog-backend-module-bitbucket-cloud:bs_1.45.3__0.5.5!backstage-plugin-catalog-backend-module-bitbucket-cloud" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-azure-devops-backend:bs_1.45.3__0.23.0!backstage-community-plugin-azure-devops-backend" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-azure-devops:bs_1.45.3__0.23.0!backstage-community-plugin-azure-devops" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-3scale-backend:bs_1.45.3__3.10.0!backstage-community-plugin-3scale-backend" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-argocd-backend:bs_1.45.3__1.0.2!backstage-community-plugin-argocd-backend" + - package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-argocd:bs_1.45.3__2.4.3!backstage-community-plugin-argocd" From d36a75b4ae9ab485b4af87291407e0229483e625 Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Tue, 3 Mar 2026 14:07:03 +0000 Subject: [PATCH 17/19] prettier --- .ibm/pipelines/lib/config.sh | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.ibm/pipelines/lib/config.sh b/.ibm/pipelines/lib/config.sh index a6ca09bcf9..2d9293dd1a 100644 --- a/.ibm/pipelines/lib/config.sh +++ b/.ibm/pipelines/lib/config.sh @@ -208,15 +208,15 @@ config::add_explicit_plugin_paths_osd_gcp() { trap "rm -rf ${catalog_index_temp_dir}" EXIT log::info "Extracting catalog index ${catalog_index_image} to find all ghcr.io plugins" - + if command -v skopeo > /dev/null 2>&1 && command -v yq > /dev/null 2>&1; then local catalog_index_local_dir="${catalog_index_temp_dir}/catalog-index-oci" mkdir -p "${catalog_index_local_dir}" - + # Try to extract the catalog index image (may fail if network is restricted, but that's okay) if skopeo copy --override-os=linux --override-arch=amd64 "docker://${catalog_index_image}" "dir:${catalog_index_local_dir}" > /dev/null 2>&1; then log::info "Successfully extracted catalog index image" - + # Extract the dynamic-plugins.default.yaml file local manifest_path="${catalog_index_local_dir}/manifest.json" if [[ -f "$manifest_path" ]]; then @@ -230,29 +230,29 @@ config::add_explicit_plugin_paths_osd_gcp() { local catalog_yaml_dir="${catalog_index_temp_dir}/catalog-yaml" mkdir -p "${catalog_yaml_dir}" tar -xf "${layer_file}" -C "${catalog_yaml_dir}" 2> /dev/null || true - + local catalog_plugins_file="${catalog_yaml_dir}/dynamic-plugins.default.yaml" if [[ -f "$catalog_plugins_file" ]]; then log::info "Found catalog index plugins file, extracting ghcr.io plugins" - + # Extract all ghcr.io plugins from the catalog index local catalog_ghcr_plugins catalog_ghcr_plugins=$(yq eval '.plugins[] | select(.package | startswith("oci://ghcr.io")) | .package' "$catalog_plugins_file" 2> /dev/null || true) - + if [[ -n "$catalog_ghcr_plugins" ]]; then while IFS= read -r catalog_plugin; do [[ -z "$catalog_plugin" ]] && continue - + # Skip if already has explicit path if [[ "$catalog_plugin" == *"!"* ]]; then continue fi - + # Infer plugin path from image name local inferred_path inferred_path=$(extract_plugin_path "$catalog_plugin") local catalog_plugin_with_path="${catalog_plugin}!${inferred_path}" - + # Check if this plugin is already in our explicit list or ConfigMap local already_added=false for known_package in "${!plugin_paths[@]}"; do @@ -263,7 +263,7 @@ config::add_explicit_plugin_paths_osd_gcp() { break fi done - + # Also check if it's already in the ConfigMap if [[ "$already_added" == "false" ]]; then local existing_in_cm @@ -272,7 +272,7 @@ config::add_explicit_plugin_paths_osd_gcp() { already_added=true fi fi - + # Add to plugin_paths map if not already there if [[ "$already_added" == "false" ]]; then plugin_paths["${catalog_plugin}"]="${inferred_path}" @@ -296,12 +296,12 @@ config::add_explicit_plugin_paths_osd_gcp() { # because the Python script processes includes (catalog index) FIRST, and if a plugin # without an explicit path is encountered, it fails before checking the main plugins list local updated=false - + # Initialize plugins array if it doesn't exist if ! yq eval '.plugins' "$temp_file" > /dev/null 2>&1; then yq eval -i '.plugins = []' "$temp_file" fi - + for plugin_package in "${!plugin_paths[@]}"; do local plugin_path="${plugin_paths[$plugin_package]}" local package_with_path="${plugin_package}!${plugin_path}" From 08c2f10e373ca71b76bd70383de9bc1a2b4a438c Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Tue, 3 Mar 2026 16:59:03 +0000 Subject: [PATCH 18/19] prevent auto detection failures by ensuring all known ghcr.io plugins have explicit paths --- .ibm/pipelines/lib/config.sh | 63 +++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/.ibm/pipelines/lib/config.sh b/.ibm/pipelines/lib/config.sh index 2d9293dd1a..5074c0b9cf 100644 --- a/.ibm/pipelines/lib/config.sh +++ b/.ibm/pipelines/lib/config.sh @@ -302,26 +302,57 @@ config::add_explicit_plugin_paths_osd_gcp() { yq eval -i '.plugins = []' "$temp_file" fi + # Helper function to get base image path (without version/tag, with oci:// prefix) + get_base_image_path() { + local package="$1" + # Extract everything before : or @ (keeps oci:// prefix) + echo "${package}" | sed -E 's|^([^:@]+).*|\1|' + } + for plugin_package in "${!plugin_paths[@]}"; do local plugin_path="${plugin_paths[$plugin_package]}" local package_with_path="${plugin_package}!${plugin_path}" - - # Check if plugin exists without explicit path in the main plugins list - local plugin_without_path - plugin_without_path=$(yq eval ".plugins[] | select(.package == \"${plugin_package}\")" "$temp_file" 2> /dev/null) - - if [[ -n "$plugin_without_path" ]]; then - # Plugin exists without explicit path, update it to include the path - yq eval -i "(.plugins[] | select(.package == \"${plugin_package}\")).package = \"${package_with_path}\"" "$temp_file" - log::info "Added explicit plugin path for: ${plugin_package} -> ${plugin_path}" - updated=true + local base_image_path + base_image_path=$(get_base_image_path "${plugin_package}") + + # Check if plugin with exact package string exists + local exact_match + exact_match=$(yq eval ".plugins[] | select(.package == \"${plugin_package}\" or .package == \"${package_with_path}\")" "$temp_file" 2> /dev/null) + + if [[ -n "$exact_match" ]]; then + # Exact match exists, ensure it has explicit path + local existing_package + existing_package=$(echo "$exact_match" | yq eval '.package' - 2> /dev/null || echo "") + if [[ "$existing_package" != *"!"* ]]; then + # Update to include explicit path + yq eval -i "(.plugins[] | select(.package == \"${plugin_package}\")).package = \"${package_with_path}\"" "$temp_file" + log::info "Added explicit plugin path for: ${plugin_package} -> ${plugin_path}" + updated=true + fi else - # Check if plugin exists with explicit path already in the main plugins list - local plugin_with_path - plugin_with_path=$(yq eval ".plugins[] | select(.package == \"${package_with_path}\")" "$temp_file" 2> /dev/null) - - if [[ -z "$plugin_with_path" ]]; then - # Plugin doesn't exist in main plugins list - ALWAYS add it with explicit path + # Check if any plugin with the same base image exists (different version) + local base_match + base_match=$(yq eval ".plugins[] | select(.package | startswith(\"${base_image_path}\"))" "$temp_file" 2> /dev/null | head -n 1) + + if [[ -n "$base_match" ]]; then + # Plugin with same base image exists, check if it needs explicit path + local existing_package + existing_package=$(echo "$base_match" | yq eval '.package' - 2> /dev/null || echo "") + if [[ -n "$existing_package" && "$existing_package" != *"!"* ]]; then + # Existing plugin doesn't have explicit path, add our version with explicit path + # (Don't remove the old one - having both ensures the one with explicit path is available) + yq eval -i ".plugins += [{\"package\": \"${package_with_path}\"}]" "$temp_file" + log::info "Added plugin with explicit path (base image already exists without path): ${package_with_path}" + updated=true + elif [[ -n "$existing_package" && "$existing_package" == *"!"* ]]; then + # Already has explicit path, but still add our known version to ensure it's available + # This ensures our known version with explicit path is present even if catalog index has different version + yq eval -i ".plugins += [{\"package\": \"${package_with_path}\"}]" "$temp_file" + log::info "Added plugin with explicit path (base image exists with path, adding known version): ${package_with_path}" + updated=true + fi + else + # No plugin with this base image exists - ALWAYS add it with explicit path # This is critical: we must add ALL ghcr.io plugins to the main plugins list # so they're available when the script processes includes, preventing auto-detection failures yq eval -i ".plugins += [{\"package\": \"${package_with_path}\"}]" "$temp_file" From 7c6f44c206d3fea423cb48cca17b17f7f9d8ed4a Mon Sep 17 00:00:00 2001 From: Fortune-Ndlovu Date: Tue, 3 Mar 2026 17:01:19 +0000 Subject: [PATCH 19/19] use single quotes --- .ibm/pipelines/lib/config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ibm/pipelines/lib/config.sh b/.ibm/pipelines/lib/config.sh index 5074c0b9cf..c79c0373ac 100644 --- a/.ibm/pipelines/lib/config.sh +++ b/.ibm/pipelines/lib/config.sh @@ -205,7 +205,7 @@ config::add_explicit_plugin_paths_osd_gcp() { local catalog_index_image="quay.io/rhdh/plugin-catalog-index:1.10" local catalog_index_temp_dir catalog_index_temp_dir=$(mktemp -d) - trap "rm -rf ${catalog_index_temp_dir}" EXIT + trap 'rm -rf "$catalog_index_temp_dir"' EXIT log::info "Extracting catalog index ${catalog_index_image} to find all ghcr.io plugins"