From d3166392c44c75088c48b7728c5d7aa2221b18e6 Mon Sep 17 00:00:00 2001 From: Josef Kopriva Date: Tue, 3 Nov 2026 09:21:41 +0100 Subject: [PATCH 1/2] ci(fbc): validate source catalogs before release builds Validate changed graph and catalog sources in repository CI and prevent automated workflows from pushing invalid catalog content. Assisted-by: Codex --- .github/workflows/create-release.yaml | 11 +++ .github/workflows/sync-catalog.yaml | 3 +- .github/workflows/validate-fbc-catalogs.yaml | 41 +++++++++++ README.md | 15 +++- utils/validate_changed_fbc_catalogs.sh | 76 ++++++++++++++++++++ 5 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/validate-fbc-catalogs.yaml create mode 100755 utils/validate_changed_fbc_catalogs.sh diff --git a/.github/workflows/create-release.yaml b/.github/workflows/create-release.yaml index b597a404..cc51a221 100644 --- a/.github/workflows/create-release.yaml +++ b/.github/workflows/create-release.yaml @@ -156,6 +156,17 @@ jobs: ./utils/render_catalog.sh done + - name: Validate updated catalog sources + env: + FBC_DIR: ${{ github.event.inputs.fbc_dir }} + VERSIONS: ${{ github.event.inputs.ocp_versions }} + run: | + IFS=',' read -ra versions <<< "${VERSIONS}" + for version in "${versions[@]}"; do + version="${version//[[:space:]]/}" + ./utils/validate_fbc_graph_sync.sh "${version}/${FBC_DIR}" + done + - name: Stage catalog changes run: git add . diff --git a/.github/workflows/sync-catalog.yaml b/.github/workflows/sync-catalog.yaml index bafd8015..b3a290eb 100644 --- a/.github/workflows/sync-catalog.yaml +++ b/.github/workflows/sync-catalog.yaml @@ -65,8 +65,7 @@ jobs: yq eval -i 'del(.entries[] | select(.schema == "io.openshift.operators.lifecycles.v1alpha1"))' $OCP_VERSION/$PACKAGE_NAME/graph.yaml FBC_DIR=$PACKAGE_NAME CATALOG_FILE="$OCP_VERSION/$PACKAGE_NAME/catalog/$PACKAGE_NAME/catalog.json" ./utils/render_catalog.sh - echo "Validating ${{ matrix.ocp_version }}/$PACKAGE_NAME/catalog/$PACKAGE_NAME" - opm validate ${{ matrix.ocp_version }}/$PACKAGE_NAME/catalog/$PACKAGE_NAME/ + ./utils/validate_fbc_graph_sync.sh "${OCP_VERSION}/${PACKAGE_NAME}" done # FIX 1: Tar the output to preserve directory structure - name: Compress Artifacts diff --git a/.github/workflows/validate-fbc-catalogs.yaml b/.github/workflows/validate-fbc-catalogs.yaml new file mode 100644 index 00000000..11ac1424 --- /dev/null +++ b/.github/workflows/validate-fbc-catalogs.yaml @@ -0,0 +1,41 @@ +name: FBC source validation + +on: + pull_request: + push: + branches: + - main + - 'release-*' + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: fbc-source-validation-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + validate: + name: Validate changed FBC catalogs + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha || github.sha }} + + - name: Install OPM + uses: ./.github/actions/install-opm + + - name: Validate catalog sources + env: + BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }} + HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" || -z "${BASE_SHA}" ]]; then + ./utils/validate_changed_fbc_catalogs.sh --all + else + ./utils/validate_changed_fbc_catalogs.sh "${BASE_SHA}" "${HEAD_SHA}" + fi diff --git a/README.md b/README.md index 941e77c3..b44fe0e0 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,8 @@ Releases in this repository follow a snapshot-based workflow. First, candidate r ## Validating a Catalog Locally -Run the same graph and catalog validation used by the FBC builder pipeline by -passing the catalog context to the validation script: +Run the same graph and catalog validation used by repository CI by passing the +catalog context to the validation script: ```bash ./utils/validate_fbc_graph_sync.sh v4.20/rhtas-operator @@ -35,3 +35,14 @@ passing the catalog context to the validation script: The script requires `opm` and `jq`. It validates both the committed catalog and its synchronization with `graph.yaml`. + +GitHub Actions runs the `Validate changed FBC catalogs` check for every pull +request and for every commit pushed to `main` or a `release-*` branch. Changes +to validation tooling cause all catalogs to be checked; otherwise only changed +catalog contexts are validated. + +The release-creation and nightly synchronization workflows run this validation +before creating their signed commits. This prevents invalid automated catalog +content from being pushed and triggering a Konflux snapshot. A Release CR must +only reference a snapshot whose source commit has a successful `Validate changed +FBC catalogs` check. diff --git a/utils/validate_changed_fbc_catalogs.sh b/utils/validate_changed_fbc_catalogs.sh new file mode 100755 index 00000000..f6f8d884 --- /dev/null +++ b/utils/validate_changed_fbc_catalogs.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +set -euo pipefail + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +repo_root="$(cd "${script_dir}/.." && pwd)" +cd "${repo_root}" + +usage() { + echo "Usage: $0 --all | [head-revision]" >&2 +} + +all_contexts() { + find . -mindepth 3 -maxdepth 3 -type f -name graph.yaml -path './v*/*/graph.yaml' \ + | sed -e 's#^\./##' -e 's#/graph.yaml$##' \ + | sort -u +} + +if [[ $# -eq 1 && "$1" == "--all" ]]; then + mapfile -t contexts < <(all_contexts) +elif [[ $# -ge 1 && $# -le 2 ]]; then + base_revision="$1" + head_revision="${2:-HEAD}" + + if ! git cat-file -e "${head_revision}^{commit}" 2>/dev/null; then + echo "Head revision ${head_revision} does not resolve to a commit." >&2 + exit 2 + fi + + if [[ "${base_revision}" =~ ^0+$ ]] || ! git cat-file -e "${base_revision}^{commit}" 2>/dev/null; then + echo "Base revision is unavailable; validating all catalogs." + mapfile -t contexts < <(all_contexts) + else + changed_files="$(git diff --name-only --diff-filter=ACDMRT "${base_revision}" "${head_revision}")" + + if grep -Eq '^utils/|^\.github/actions/install-opm/action\.yaml$|^\.github/workflows/(create-release|sync-catalog|validate-fbc-catalogs)\.yaml$' \ + <<< "${changed_files}"; then + echo "Validation tooling changed; validating all catalogs." + mapfile -t contexts < <(all_contexts) + else + mapfile -t contexts < <( + awk -F/ ' + $1 ~ /^v[0-9]+\.[0-9]+$/ && + NF >= 3 && + ($3 == "graph.yaml" || $3 == "catalog") { + print $1 "/" $2 + } + ' <<< "${changed_files}" | sort -u + ) + fi + fi +else + usage + exit 2 +fi + +if [[ ${#contexts[@]} -eq 0 ]]; then + echo "No changed FBC catalogs require validation." + exit 0 +fi + +echo "Catalog contexts to validate:" +printf ' %s\n' "${contexts[@]}" + +failed=0 +for context in "${contexts[@]}"; do + if [[ ! -d "${context}" ]]; then + echo "Catalog context ${context} was removed; skipping." + continue + fi + + if ! "${script_dir}/validate_fbc_graph_sync.sh" "${context}"; then + failed=1 + fi +done + +exit "${failed}" From 685fa983782625600fa81e9d81aebb64e24f9a0c Mon Sep 17 00:00:00 2001 From: Josef Kopriva Date: Wed, 4 Nov 2026 08:45:05 +0100 Subject: [PATCH 2/2] fix(ci): validate both paths of renamed catalog files Inspect rename and copy source paths as well as destinations so required graph or catalog files cannot bypass changed-catalog validation. Assisted-by: Codex --- utils/validate_changed_fbc_catalogs.sh | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/utils/validate_changed_fbc_catalogs.sh b/utils/validate_changed_fbc_catalogs.sh index f6f8d884..f0f2d786 100755 --- a/utils/validate_changed_fbc_catalogs.sh +++ b/utils/validate_changed_fbc_catalogs.sh @@ -30,7 +30,20 @@ elif [[ $# -ge 1 && $# -le 2 ]]; then echo "Base revision is unavailable; validating all catalogs." mapfile -t contexts < <(all_contexts) else - changed_files="$(git diff --name-only --diff-filter=ACDMRT "${base_revision}" "${head_revision}")" + changed_files="$( + git diff --name-status --find-renames --find-copies --diff-filter=ACDMRT \ + "${base_revision}" "${head_revision}" \ + | awk -F '\t' ' + $1 ~ /^[RC]/ { + print $2 + print $3 + next + } + { + print $2 + } + ' + )" if grep -Eq '^utils/|^\.github/actions/install-opm/action\.yaml$|^\.github/workflows/(create-release|sync-catalog|validate-fbc-catalogs)\.yaml$' \ <<< "${changed_files}"; then