From 292c62ff078a1640d1a6bc727543484873354a1d Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Tue, 10 Dec 2024 12:22:38 +0100 Subject: [PATCH 01/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 fbc/fbc-post-release.yaml diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml new file mode 100644 index 0000000..78f2d7a --- /dev/null +++ b/fbc/fbc-post-release.yaml @@ -0,0 +1,30 @@ +--- +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + name: fbc-post-release +spec: + description: WIP + params: + - name: released_version + type: string + - name: snapshot + type: string + tasks: + - name: get-info + params: + - name: SNAPSHOT + value: "$(params.snapshot)" + taskSpec: + params: + - name: SNAPSHOT + type: string + steps: + - name: get-info + image: quay.io/konflux-ci/release-service-utils:e633d51cd41d73e4b3310face21bb980af7a662f + script: | + #!/usr/bin/env sh + set -eo pipefail + + echo $(params.SNAPSHOT) + get-resource "snapshot" $(params.SNAPSHOT) \ No newline at end of file From e9d2701ae7c15f14afc4b032903e4a46ae74925a Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Tue, 10 Dec 2024 13:12:42 +0100 Subject: [PATCH 02/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 78f2d7a..38777ae 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -6,8 +6,6 @@ metadata: spec: description: WIP params: - - name: released_version - type: string - name: snapshot type: string tasks: From 42353bd52233448cf29e88cd4fd3b934a67e20e4 Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Wed, 11 Dec 2024 14:05:54 +0100 Subject: [PATCH 03/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 38777ae..5f1a90c 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -13,16 +13,28 @@ spec: params: - name: SNAPSHOT value: "$(params.snapshot)" + - name: IIB_INDEX_IMAGE + value: "$(results.iibIndexImage)" taskSpec: params: - name: SNAPSHOT type: string + - name: IIB_INDEX_IMAGE + type: string steps: - name: get-info - image: quay.io/konflux-ci/release-service-utils:e633d51cd41d73e4b3310face21bb980af7a662f + image: quay.io/konflux-ci/release-service-utils:cd12f6a509363ae511bf09d50be73d5edb416cdd script: | - #!/usr/bin/env sh - set -eo pipefail + #!/usr/bin/env bash + set -exo pipefail echo $(params.SNAPSHOT) + echo $(params.IIB_INDEX_IMAGE) + + snapshot=$(echo "$(params.SNAPSHOT)" | awk -F'/' '{print $2}') + snapshot_data=$(kubectl get snapshot $snapshot -oyaml) + fbc_fragment=$(echo $snapshot_data | yq '.spec.components[0].containerImage') + git_commit=$(echo $snapshot_data | yq '.spec.components[0].source.git.revision') + git_repo=$(echo $snapshot_data | yq '.spec.components[0].source.git.url') + get-resource "snapshot" $(params.SNAPSHOT) \ No newline at end of file From 269cb4602e95107095151073fc197f39777c819e Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Wed, 11 Dec 2024 14:55:53 +0100 Subject: [PATCH 04/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 5f1a90c..91d3960 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -8,13 +8,15 @@ spec: params: - name: snapshot type: string + - name: iibIndexImage + type: string tasks: - name: get-info params: - name: SNAPSHOT value: "$(params.snapshot)" - name: IIB_INDEX_IMAGE - value: "$(results.iibIndexImage)" + value: "$(params.iibIndexImage)" taskSpec: params: - name: SNAPSHOT From 8dfa4b755804d50850489d7ae84f531bec4c79bd Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Wed, 11 Dec 2024 17:37:13 +0100 Subject: [PATCH 05/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 91d3960..dc8a347 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -8,20 +8,26 @@ spec: params: - name: snapshot type: string - - name: iibIndexImage + - name: cnv_version + type: string + - name: releaseplan_id type: string tasks: - name: get-info params: - name: SNAPSHOT value: "$(params.snapshot)" - - name: IIB_INDEX_IMAGE - value: "$(params.iibIndexImage)" + - name: CNV_VERSION + value: "$(params.cnv_version)" + - name: RELEASEPLAN_ID + value: "$(params.releaseplan_id)" taskSpec: params: - name: SNAPSHOT type: string - - name: IIB_INDEX_IMAGE + - name: CNV_VERSION + type: string + - name: RELEASEPLAN_ID type: string steps: - name: get-info @@ -30,11 +36,20 @@ spec: #!/usr/bin/env bash set -exo pipefail - echo $(params.SNAPSHOT) - echo $(params.IIB_INDEX_IMAGE) + snapshot_id=$(echo "$(params.SNAPSHOT)" | awk -F'/' '{print $2}') + snapshot_data=$(kubectl get snapshot $snapshot_id -oyaml) + + release_id=$(kubectl get release -o json | \ + jq -r --arg snapshot "$snapshot_id" --arg releaseplan "$(params.RELEASEPLAN_ID)" \ + '.items[] | select(.spec.snapshot == $snapshot and .spec.releasePlan == $releaseplan) | .metadata.name' | head -n 1) + + managed_pipelinerun=$(kubectl get release $release_id -oyaml | yq '.status.managedProcessing.pipelineRun') + managed_ns=$(echo "$managed_pipelinerun" | awk -F'/' '{print $1}') + managed_pipelinerun=$(echo "$managed_pipelinerun" | awk -F'/' '{print $2}') + + index_image=$(kubectl get pipelinerun $managed_pipelinerun -n $managed_ns -oyaml | yq '.status.results[] | select(.name == "iibIndexImage") | .value') + from_index="registry-proxy.engineering.redhat.com/rh-osbs/iib-pub-pending:$(params.CNV_VERSION)" - snapshot=$(echo "$(params.SNAPSHOT)" | awk -F'/' '{print $2}') - snapshot_data=$(kubectl get snapshot $snapshot -oyaml) fbc_fragment=$(echo $snapshot_data | yq '.spec.components[0].containerImage') git_commit=$(echo $snapshot_data | yq '.spec.components[0].source.git.revision') git_repo=$(echo $snapshot_data | yq '.spec.components[0].source.git.url') From 5598a01fa487ccec03b63b04729a26f1fb1193a4 Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Wed, 11 Dec 2024 18:20:38 +0100 Subject: [PATCH 06/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index dc8a347..921c309 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -39,19 +39,17 @@ spec: snapshot_id=$(echo "$(params.SNAPSHOT)" | awk -F'/' '{print $2}') snapshot_data=$(kubectl get snapshot $snapshot_id -oyaml) - release_id=$(kubectl get release -o json | \ + fbc_fragment=$(echo $snapshot_data | yq '.spec.components[0].containerImage') + git_commit=$(echo $snapshot_data | yq '.spec.components[0].source.git.revision') + git_repo=$(echo $snapshot_data | yq '.spec.components[0].source.git.url') + + release_id=$(kubectl get release --sort-by=.metadata.creationTimestamp -o json | \ jq -r --arg snapshot "$snapshot_id" --arg releaseplan "$(params.RELEASEPLAN_ID)" \ - '.items[] | select(.spec.snapshot == $snapshot and .spec.releasePlan == $releaseplan) | .metadata.name' | head -n 1) + '.items[] | select(.spec.snapshot == $snapshot and .spec.releasePlan == $releaseplan) | .metadata.name' | tail -n 1) managed_pipelinerun=$(kubectl get release $release_id -oyaml | yq '.status.managedProcessing.pipelineRun') managed_ns=$(echo "$managed_pipelinerun" | awk -F'/' '{print $1}') managed_pipelinerun=$(echo "$managed_pipelinerun" | awk -F'/' '{print $2}') index_image=$(kubectl get pipelinerun $managed_pipelinerun -n $managed_ns -oyaml | yq '.status.results[] | select(.name == "iibIndexImage") | .value') - from_index="registry-proxy.engineering.redhat.com/rh-osbs/iib-pub-pending:$(params.CNV_VERSION)" - - fbc_fragment=$(echo $snapshot_data | yq '.spec.components[0].containerImage') - git_commit=$(echo $snapshot_data | yq '.spec.components[0].source.git.revision') - git_repo=$(echo $snapshot_data | yq '.spec.components[0].source.git.url') - - get-resource "snapshot" $(params.SNAPSHOT) \ No newline at end of file + from_index="registry-proxy.engineering.redhat.com/rh-osbs/iib-pub-pending:$(params.CNV_VERSION)" \ No newline at end of file From ecb1b8315c422eec64384e3f59561c1bb954faf4 Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Thu, 12 Dec 2024 09:39:29 +0100 Subject: [PATCH 07/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 921c309..e810446 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -37,19 +37,19 @@ spec: set -exo pipefail snapshot_id=$(echo "$(params.SNAPSHOT)" | awk -F'/' '{print $2}') - snapshot_data=$(kubectl get snapshot $snapshot_id -oyaml) + snapshot_data=$(kubectl get snapshot "${snapshot_id}" -oyaml) - fbc_fragment=$(echo $snapshot_data | yq '.spec.components[0].containerImage') - git_commit=$(echo $snapshot_data | yq '.spec.components[0].source.git.revision') - git_repo=$(echo $snapshot_data | yq '.spec.components[0].source.git.url') + fbc_fragment=$(echo "${snapshot_data}" | yq '.spec.components[0].containerImage') + git_commit=$(echo "${snapshot_data}" | yq '.spec.components[0].source.git.revision') + git_repo=$(echo "${snapshot_data}" | yq '.spec.components[0].source.git.url') release_id=$(kubectl get release --sort-by=.metadata.creationTimestamp -o json | \ - jq -r --arg snapshot "$snapshot_id" --arg releaseplan "$(params.RELEASEPLAN_ID)" \ + jq -r --arg snapshot "${snapshot_id}" --arg releaseplan "$(params.RELEASEPLAN_ID)" \ '.items[] | select(.spec.snapshot == $snapshot and .spec.releasePlan == $releaseplan) | .metadata.name' | tail -n 1) - managed_pipelinerun=$(kubectl get release $release_id -oyaml | yq '.status.managedProcessing.pipelineRun') - managed_ns=$(echo "$managed_pipelinerun" | awk -F'/' '{print $1}') - managed_pipelinerun=$(echo "$managed_pipelinerun" | awk -F'/' '{print $2}') + managed_pipelinerun=$(kubectl get release "${release_id}" -oyaml | yq '.status.managedProcessing.pipelineRun') + managed_ns=$(echo "${managed_pipelinerun}" | awk -F'/' '{print $1}') + managed_pipelinerun=$(echo "${managed_pipelinerun}" | awk -F'/' '{print $2}') - index_image=$(kubectl get pipelinerun $managed_pipelinerun -n $managed_ns -oyaml | yq '.status.results[] | select(.name == "iibIndexImage") | .value') + index_image=$(kubectl get pipelinerun "${managed_pipelinerun}" -n "${managed_ns}" -oyaml | yq '.status.results[] | select(.name == "iibIndexImage") | .value') from_index="registry-proxy.engineering.redhat.com/rh-osbs/iib-pub-pending:$(params.CNV_VERSION)" \ No newline at end of file From cf257c463e0c824a893612018ab01a2686990803 Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Thu, 12 Dec 2024 16:47:09 +0100 Subject: [PATCH 08/88] tesT Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index e810446..2f33101 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -40,8 +40,6 @@ spec: snapshot_data=$(kubectl get snapshot "${snapshot_id}" -oyaml) fbc_fragment=$(echo "${snapshot_data}" | yq '.spec.components[0].containerImage') - git_commit=$(echo "${snapshot_data}" | yq '.spec.components[0].source.git.revision') - git_repo=$(echo "${snapshot_data}" | yq '.spec.components[0].source.git.url') release_id=$(kubectl get release --sort-by=.metadata.creationTimestamp -o json | \ jq -r --arg snapshot "${snapshot_id}" --arg releaseplan "$(params.RELEASEPLAN_ID)" \ @@ -51,5 +49,15 @@ spec: managed_ns=$(echo "${managed_pipelinerun}" | awk -F'/' '{print $1}') managed_pipelinerun=$(echo "${managed_pipelinerun}" | awk -F'/' '{print $2}') - index_image=$(kubectl get pipelinerun "${managed_pipelinerun}" -n "${managed_ns}" -oyaml | yq '.status.results[] | select(.name == "iibIndexImage") | .value') - from_index="registry-proxy.engineering.redhat.com/rh-osbs/iib-pub-pending:$(params.CNV_VERSION)" \ No newline at end of file + # index_image=$(kubectl get pipelinerun "${managed_pipelinerun}" -n "${managed_ns}" -oyaml | yq '.status.results[] | select(.name == "iibIndexImage") | .value') + from_index="registry-proxy.engineering.redhat.com/rh-osbs/iib-pub-pending:$(params.CNV_VERSION)" + + git_commit=$(echo "${snapshot_data}" | yq '.spec.components[0].source.git.revision') + git_repo=$(echo "${snapshot_data}" | yq '.spec.components[0].source.git.url') + mkdir cnv-fbc && cd cnv-fbc + git init + git remote add origin "${git_repo}.git" + git fetch origin "${git_commit}" --depth 1 + git checkout "${git_commit}" + image_sha=$(yq '.image' $(params.CNV_VERSION)/updated_image.yaml) + channel=$(yq '.channel' $(params.CNV_VERSION)/updated_image.yaml) From 7e9c20575e393e1db59d7c1167927fbed8184644 Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Fri, 13 Dec 2024 09:30:43 +0100 Subject: [PATCH 09/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 2f33101..b3fb2dc 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -54,7 +54,7 @@ spec: git_commit=$(echo "${snapshot_data}" | yq '.spec.components[0].source.git.revision') git_repo=$(echo "${snapshot_data}" | yq '.spec.components[0].source.git.url') - mkdir cnv-fbc && cd cnv-fbc + gitdir=$(mktemp -d) && cd "${gitdir}" git init git remote add origin "${git_repo}.git" git fetch origin "${git_commit}" --depth 1 From 873012a4894a2f965702fdebb7d529c291476898 Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Fri, 13 Dec 2024 16:58:11 +0100 Subject: [PATCH 10/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index b3fb2dc..f360463 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -34,7 +34,7 @@ spec: image: quay.io/konflux-ci/release-service-utils:cd12f6a509363ae511bf09d50be73d5edb416cdd script: | #!/usr/bin/env bash - set -exo pipefail + set -eo pipefail snapshot_id=$(echo "$(params.SNAPSHOT)" | awk -F'/' '{print $2}') snapshot_data=$(kubectl get snapshot "${snapshot_id}" -oyaml) @@ -44,12 +44,7 @@ spec: release_id=$(kubectl get release --sort-by=.metadata.creationTimestamp -o json | \ jq -r --arg snapshot "${snapshot_id}" --arg releaseplan "$(params.RELEASEPLAN_ID)" \ '.items[] | select(.spec.snapshot == $snapshot and .spec.releasePlan == $releaseplan) | .metadata.name' | tail -n 1) - - managed_pipelinerun=$(kubectl get release "${release_id}" -oyaml | yq '.status.managedProcessing.pipelineRun') - managed_ns=$(echo "${managed_pipelinerun}" | awk -F'/' '{print $1}') - managed_pipelinerun=$(echo "${managed_pipelinerun}" | awk -F'/' '{print $2}') - - # index_image=$(kubectl get pipelinerun "${managed_pipelinerun}" -n "${managed_ns}" -oyaml | yq '.status.results[] | select(.name == "iibIndexImage") | .value') + index_image=$(kubectl get release "${release_id}" -oyaml | yq '.status.artifacts.index_image.index_image') from_index="registry-proxy.engineering.redhat.com/rh-osbs/iib-pub-pending:$(params.CNV_VERSION)" git_commit=$(echo "${snapshot_data}" | yq '.spec.components[0].source.git.revision') @@ -61,3 +56,9 @@ spec: git checkout "${git_commit}" image_sha=$(yq '.image' $(params.CNV_VERSION)/updated_image.yaml) channel=$(yq '.channel' $(params.CNV_VERSION)/updated_image.yaml) + + echo "index_image: ${index_image}" + echo "from_index: ${from_index}" + echo "fbc_fragment: ${fbc_fragment}" + echo "image_sha to ensure integrity: ${image_sha}" + echo "channel: ${channel}" From 0a5b6b956c12a7e7229b45cd86199abd6b3a8ceb Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Mon, 16 Dec 2024 15:14:53 +0100 Subject: [PATCH 11/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index f360463..d901c39 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -56,9 +56,11 @@ spec: git checkout "${git_commit}" image_sha=$(yq '.image' $(params.CNV_VERSION)/updated_image.yaml) channel=$(yq '.channel' $(params.CNV_VERSION)/updated_image.yaml) + hco_bundle_version=$(yq '.hco-bundle-version' $(params.CNV_VERSION)/updated_image.yaml) echo "index_image: ${index_image}" echo "from_index: ${from_index}" echo "fbc_fragment: ${fbc_fragment}" echo "image_sha to ensure integrity: ${image_sha}" echo "channel: ${channel}" + echo "hco-bundle-version: ${hco_bundle_version}" From b0e8fb545f31ea40470d27a52813cf02728e7d8a Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Thu, 19 Dec 2024 12:47:52 +0100 Subject: [PATCH 12/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index d901c39..34ba766 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -32,6 +32,9 @@ spec: steps: - name: get-info image: quay.io/konflux-ci/release-service-utils:cd12f6a509363ae511bf09d50be73d5edb416cdd + envFrom: + - secretRef: + name: cnv-ci-release-token script: | #!/usr/bin/env bash set -eo pipefail @@ -49,7 +52,7 @@ spec: git_commit=$(echo "${snapshot_data}" | yq '.spec.components[0].source.git.revision') git_repo=$(echo "${snapshot_data}" | yq '.spec.components[0].source.git.url') - gitdir=$(mktemp -d) && cd "${gitdir}" + gitfbcdir=$(mktemp -d) && cd "${gitfbcdir}" git init git remote add origin "${git_repo}.git" git fetch origin "${git_commit}" --depth 1 @@ -58,9 +61,20 @@ spec: channel=$(yq '.channel' $(params.CNV_VERSION)/updated_image.yaml) hco_bundle_version=$(yq '.hco-bundle-version' $(params.CNV_VERSION)/updated_image.yaml) - echo "index_image: ${index_image}" - echo "from_index: ${from_index}" - echo "fbc_fragment: ${fbc_fragment}" - echo "image_sha to ensure integrity: ${image_sha}" - echo "channel: ${channel}" - echo "hco-bundle-version: ${hco_bundle_version}" + gitpayloaddir=$(mktemp -d) && cd "${gitpayloaddir}" + git clone https://${github_token}@github.com/openshift-cnv/cnv-fbc-payloads.git && cd cnv-fbc-payloads + git config --global user.name "${github_username}" + git config --global user.email "no-reply@redhat.com" + + mkdir "$(params.CNV_VERSION)" + touch "$(params.CNV_VERSION)/payload.yaml" + yq e '.index_image = ${index_image}' -i $(params.CNV_VERSION)/payload.yml + yq e '.from_index = ${from_index}' -i $(params.CNV_VERSION)/payload.yml + yq e '.fbc_fragment = ${fbc_fragment}' -i $(params.CNV_VERSION)/payload.yml + yq e '.image_sha = ${image_sha}' -i $(params.CNV_VERSION)/payload.yml + yq e '.channel = ${channel}' -i $(params.CNV_VERSION)/payload.yml + yq e '.hco_bundle_version = ${hco_bundle_version}' -i $(params.CNV_VERSION)/payload.yml + + git add . + git commit -m "Update payload" + git push origin main From c0907653d02cf86ba3305ee7408136ab4674646c Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Thu, 19 Dec 2024 13:49:10 +0100 Subject: [PATCH 13/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 34ba766..db16619 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -68,12 +68,12 @@ spec: mkdir "$(params.CNV_VERSION)" touch "$(params.CNV_VERSION)/payload.yaml" - yq e '.index_image = ${index_image}' -i $(params.CNV_VERSION)/payload.yml - yq e '.from_index = ${from_index}' -i $(params.CNV_VERSION)/payload.yml - yq e '.fbc_fragment = ${fbc_fragment}' -i $(params.CNV_VERSION)/payload.yml - yq e '.image_sha = ${image_sha}' -i $(params.CNV_VERSION)/payload.yml - yq e '.channel = ${channel}' -i $(params.CNV_VERSION)/payload.yml - yq e '.hco_bundle_version = ${hco_bundle_version}' -i $(params.CNV_VERSION)/payload.yml + yq e '.index_image = ${index_image}' -i $(params.CNV_VERSION)/payload.yaml + yq e '.from_index = ${from_index}' -i $(params.CNV_VERSION)/payload.yaml + yq e '.fbc_fragment = ${fbc_fragment}' -i $(params.CNV_VERSION)/payload.yaml + yq e '.image_sha = ${image_sha}' -i $(params.CNV_VERSION)/payload.yaml + yq e '.channel = ${channel}' -i $(params.CNV_VERSION)/payload.yaml + yq e '.hco_bundle_version = ${hco_bundle_version}' -i $(params.CNV_VERSION)/payload.yaml git add . git commit -m "Update payload" From f3100b172116aaebd7604c762e7a00e6aa4d3b59 Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Thu, 19 Dec 2024 14:05:57 +0100 Subject: [PATCH 14/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index db16619..33428dd 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -68,12 +68,12 @@ spec: mkdir "$(params.CNV_VERSION)" touch "$(params.CNV_VERSION)/payload.yaml" - yq e '.index_image = ${index_image}' -i $(params.CNV_VERSION)/payload.yaml - yq e '.from_index = ${from_index}' -i $(params.CNV_VERSION)/payload.yaml - yq e '.fbc_fragment = ${fbc_fragment}' -i $(params.CNV_VERSION)/payload.yaml - yq e '.image_sha = ${image_sha}' -i $(params.CNV_VERSION)/payload.yaml - yq e '.channel = ${channel}' -i $(params.CNV_VERSION)/payload.yaml - yq e '.hco_bundle_version = ${hco_bundle_version}' -i $(params.CNV_VERSION)/payload.yaml + yq e '.index_image = "${index_image}"' -i $(params.CNV_VERSION)/payload.yaml + yq e '.from_index = "${from_index}"' -i $(params.CNV_VERSION)/payload.yaml + yq e '.fbc_fragment = "${fbc_fragment}"' -i $(params.CNV_VERSION)/payload.yaml + yq e '.image_sha = "${image_sha}"' -i $(params.CNV_VERSION)/payload.yaml + yq e '.channel = "${channel}"' -i $(params.CNV_VERSION)/payload.yaml + yq e '.hco_bundle_version = "${hco_bundle_version}"' -i $(params.CNV_VERSION)/payload.yaml git add . git commit -m "Update payload" From 8622961ca4c09528020e3542e8b6e92eb08a597b Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Thu, 19 Dec 2024 14:19:15 +0100 Subject: [PATCH 15/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 33428dd..a18a95d 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -68,12 +68,12 @@ spec: mkdir "$(params.CNV_VERSION)" touch "$(params.CNV_VERSION)/payload.yaml" - yq e '.index_image = "${index_image}"' -i $(params.CNV_VERSION)/payload.yaml - yq e '.from_index = "${from_index}"' -i $(params.CNV_VERSION)/payload.yaml - yq e '.fbc_fragment = "${fbc_fragment}"' -i $(params.CNV_VERSION)/payload.yaml - yq e '.image_sha = "${image_sha}"' -i $(params.CNV_VERSION)/payload.yaml - yq e '.channel = "${channel}"' -i $(params.CNV_VERSION)/payload.yaml - yq e '.hco_bundle_version = "${hco_bundle_version}"' -i $(params.CNV_VERSION)/payload.yaml + yq e ".index_image = \"${index_image}\"" -i $(params.CNV_VERSION)/payload.yaml + yq e ".from_index = \"${from_index}\"" -i $(params.CNV_VERSION)/payload.yaml + yq e ".fbc_fragment = \"${fbc_fragment}\"" -i $(params.CNV_VERSION)/payload.yaml + yq e ".image_sha = \"${image_sha}\"" -i $(params.CNV_VERSION)/payload.yaml + yq e ".channel = \"${channel}\"" -i $(params.CNV_VERSION)/payload.yaml + yq e ".hco_bundle_version = \"${hco_bundle_version}\"" -i $(params.CNV_VERSION)/payload.yaml git add . git commit -m "Update payload" From 0ed659cf50cf064c853d6a4bbed502709e0136a6 Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Thu, 19 Dec 2024 14:35:08 +0100 Subject: [PATCH 16/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index a18a95d..5d9eedc 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -66,7 +66,7 @@ spec: git config --global user.name "${github_username}" git config --global user.email "no-reply@redhat.com" - mkdir "$(params.CNV_VERSION)" + mkdir -p "$(params.CNV_VERSION)" touch "$(params.CNV_VERSION)/payload.yaml" yq e ".index_image = \"${index_image}\"" -i $(params.CNV_VERSION)/payload.yaml yq e ".from_index = \"${from_index}\"" -i $(params.CNV_VERSION)/payload.yaml From a7abbbf559c501ff9afd53b50337635f57f878ee Mon Sep 17 00:00:00 2001 From: Axuba Date: Tue, 31 Dec 2024 11:48:24 +0100 Subject: [PATCH 17/88] Add snapshot id parameter to be also exported --- fbc/fbc-post-release.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 5d9eedc..decdc98 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -69,6 +69,7 @@ spec: mkdir -p "$(params.CNV_VERSION)" touch "$(params.CNV_VERSION)/payload.yaml" yq e ".index_image = \"${index_image}\"" -i $(params.CNV_VERSION)/payload.yaml + yq e ".snapshot_id = \"${snapshot_id}\"" -i $(params.CNV_VERSION)/payload.yaml yq e ".from_index = \"${from_index}\"" -i $(params.CNV_VERSION)/payload.yaml yq e ".fbc_fragment = \"${fbc_fragment}\"" -i $(params.CNV_VERSION)/payload.yaml yq e ".image_sha = \"${image_sha}\"" -i $(params.CNV_VERSION)/payload.yaml From 9e83286ae8908d40c2c10af7fe5b1623a08948fb Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Wed, 15 Jan 2025 15:00:07 +0100 Subject: [PATCH 18/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index decdc98..614bfa9 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -67,13 +67,15 @@ spec: git config --global user.email "no-reply@redhat.com" mkdir -p "$(params.CNV_VERSION)" - touch "$(params.CNV_VERSION)/payload.yaml" + echo "" > "$(params.CNV_VERSION)/payload.yaml" yq e ".index_image = \"${index_image}\"" -i $(params.CNV_VERSION)/payload.yaml yq e ".snapshot_id = \"${snapshot_id}\"" -i $(params.CNV_VERSION)/payload.yaml yq e ".from_index = \"${from_index}\"" -i $(params.CNV_VERSION)/payload.yaml yq e ".fbc_fragment = \"${fbc_fragment}\"" -i $(params.CNV_VERSION)/payload.yaml - yq e ".image_sha = \"${image_sha}\"" -i $(params.CNV_VERSION)/payload.yaml yq e ".channel = \"${channel}\"" -i $(params.CNV_VERSION)/payload.yaml + yq e ".hco_bundle_registry_by_sha = \"${image_sha}\"" -i $(params.CNV_VERSION)/payload.yaml + image_base=$(echo "${image_sha}" | cut -d'@' -f1) + yq e ".hco_bundle_registry_by_tag = \"${image_base}:${hco_bundle_version}\"" -i $(params.CNV_VERSION)/payload.yaml yq e ".hco_bundle_version = \"${hco_bundle_version}\"" -i $(params.CNV_VERSION)/payload.yaml git add . From 0fe16e435d9746eb97b60d744c0717befb433778 Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Thu, 16 Jan 2025 12:32:58 +0100 Subject: [PATCH 19/88] test Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 614bfa9..8e383fe 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -4,7 +4,7 @@ kind: Pipeline metadata: name: fbc-post-release spec: - description: WIP + description: This tasks gets all the required data of an FBC build and commits it to a payload repository to be used in a GitOps environment. params: - name: snapshot type: string @@ -31,7 +31,7 @@ spec: type: string steps: - name: get-info - image: quay.io/konflux-ci/release-service-utils:cd12f6a509363ae511bf09d50be73d5edb416cdd + image: quay.io/konflux-ci/release-service-utils:0a58b6a6b562879e89395636d97931f2dcbb494c envFrom: - secretRef: name: cnv-ci-release-token @@ -40,13 +40,18 @@ spec: set -eo pipefail snapshot_id=$(echo "$(params.SNAPSHOT)" | awk -F'/' '{print $2}') - snapshot_data=$(kubectl get snapshot "${snapshot_id}" -oyaml) - - fbc_fragment=$(echo "${snapshot_data}" | yq '.spec.components[0].containerImage') - release_id=$(kubectl get release --sort-by=.metadata.creationTimestamp -o json | \ jq -r --arg snapshot "${snapshot_id}" --arg releaseplan "$(params.RELEASEPLAN_ID)" \ '.items[] | select(.spec.snapshot == $snapshot and .spec.releasePlan == $releaseplan) | .metadata.name' | tail -n 1) + + released_status=$(kubectl get release "${release_id}" -oyaml | yq '.status.conditions[] | select(.type == "Released") | .status') + if [ "$released_status" != "True" ]; then + echo "Release failed. Not continuing with post-release." + exit 1 + fi + + snapshot_data=$(kubectl get snapshot "${snapshot_id}" -oyaml) + fbc_fragment=$(echo "${snapshot_data}" | yq '.spec.components[0].containerImage') index_image=$(kubectl get release "${release_id}" -oyaml | yq '.status.artifacts.index_image.index_image') from_index="registry-proxy.engineering.redhat.com/rh-osbs/iib-pub-pending:$(params.CNV_VERSION)" From 8d3c9a0e80a94cf7d19a06f821b0a258fd690991 Mon Sep 17 00:00:00 2001 From: Axuba Date: Mon, 20 Jan 2025 11:01:28 +0100 Subject: [PATCH 20/88] Update fbc-post-release.yaml --- fbc/fbc-post-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 8e383fe..d19832f 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -44,7 +44,7 @@ spec: jq -r --arg snapshot "${snapshot_id}" --arg releaseplan "$(params.RELEASEPLAN_ID)" \ '.items[] | select(.spec.snapshot == $snapshot and .spec.releasePlan == $releaseplan) | .metadata.name' | tail -n 1) - released_status=$(kubectl get release "${release_id}" -oyaml | yq '.status.conditions[] | select(.type == "Released") | .status') + released_status=$(kubectl get release "${release_id}" -oyaml | yq '.status.conditions[] | select(.type == "ManagedPipelineProcessed") | .status') if [ "$released_status" != "True" ]; then echo "Release failed. Not continuing with post-release." exit 1 From 67909fd61ac3fa96d5c7f0b528ec113bc77037ff Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 30 Jan 2025 10:15:31 +0100 Subject: [PATCH 21/88] Add version and releasePlan null params --- fbc/fbc-post-release.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index d19832f..f5b6f50 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -82,6 +82,8 @@ spec: image_base=$(echo "${image_sha}" | cut -d'@' -f1) yq e ".hco_bundle_registry_by_tag = \"${image_base}:${hco_bundle_version}\"" -i $(params.CNV_VERSION)/payload.yaml yq e ".hco_bundle_version = \"${hco_bundle_version}\"" -i $(params.CNV_VERSION)/payload.yaml + yq e ".version = null" -i $(params.CNV_VERSION)/payload.yaml + yq e ".releasePlan = null" -i $(params.CNV_VERSION)/payload.yaml git add . git commit -m "Update payload" From 4b00938eb1191fc3cd06efb513193c1fe358fc6d Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Thu, 30 Jan 2025 15:58:30 +0100 Subject: [PATCH 22/88] Update script Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index f5b6f50..df4afa0 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -50,10 +50,11 @@ spec: exit 1 fi + cnv_version="$(params.CNV_VERSION)" snapshot_data=$(kubectl get snapshot "${snapshot_id}" -oyaml) fbc_fragment=$(echo "${snapshot_data}" | yq '.spec.components[0].containerImage') index_image=$(kubectl get release "${release_id}" -oyaml | yq '.status.artifacts.index_image.index_image') - from_index="registry-proxy.engineering.redhat.com/rh-osbs/iib-pub-pending:$(params.CNV_VERSION)" + from_index="registry-proxy.engineering.redhat.com/rh-osbs/iib-pub-pending:${cnv_version}" git_commit=$(echo "${snapshot_data}" | yq '.spec.components[0].source.git.revision') git_repo=$(echo "${snapshot_data}" | yq '.spec.components[0].source.git.url') @@ -62,28 +63,29 @@ spec: git remote add origin "${git_repo}.git" git fetch origin "${git_commit}" --depth 1 git checkout "${git_commit}" - image_sha=$(yq '.image' $(params.CNV_VERSION)/updated_image.yaml) - channel=$(yq '.channel' $(params.CNV_VERSION)/updated_image.yaml) - hco_bundle_version=$(yq '.hco-bundle-version' $(params.CNV_VERSION)/updated_image.yaml) + image_sha=$(yq '.image' ${cnv_version}/updated_image.yaml) + channel=$(yq '.channel' ${cnv_version}/updated_image.yaml) + hco_bundle_version=$(yq '.hco-bundle-version' ${cnv_version}/updated_image.yaml) gitpayloaddir=$(mktemp -d) && cd "${gitpayloaddir}" git clone https://${github_token}@github.com/openshift-cnv/cnv-fbc-payloads.git && cd cnv-fbc-payloads git config --global user.name "${github_username}" git config --global user.email "no-reply@redhat.com" - mkdir -p "$(params.CNV_VERSION)" - echo "" > "$(params.CNV_VERSION)/payload.yaml" - yq e ".index_image = \"${index_image}\"" -i $(params.CNV_VERSION)/payload.yaml - yq e ".snapshot_id = \"${snapshot_id}\"" -i $(params.CNV_VERSION)/payload.yaml - yq e ".from_index = \"${from_index}\"" -i $(params.CNV_VERSION)/payload.yaml - yq e ".fbc_fragment = \"${fbc_fragment}\"" -i $(params.CNV_VERSION)/payload.yaml - yq e ".channel = \"${channel}\"" -i $(params.CNV_VERSION)/payload.yaml - yq e ".hco_bundle_registry_by_sha = \"${image_sha}\"" -i $(params.CNV_VERSION)/payload.yaml + save_folder="${cnv_version//./-}/stages/nightly/build" + mkdir -p "${save_folder}" + echo "" > "${save_folder}/payload.yaml" + yq e ".index_image = \"${index_image}\"" -i ${save_folder}/payload.yaml + yq e ".snapshot_id = \"${snapshot_id}\"" -i ${save_folder}/payload.yaml + yq e ".from_index = \"${from_index}\"" -i ${save_folder}/payload.yaml + yq e ".fbc_fragment = \"${fbc_fragment}\"" -i ${save_folder}/payload.yaml + yq e ".channel = \"${channel}\"" -i ${save_folder}/payload.yaml + yq e ".hco_bundle_registry_by_sha = \"${image_sha}\"" -i ${save_folder}/payload.yaml image_base=$(echo "${image_sha}" | cut -d'@' -f1) - yq e ".hco_bundle_registry_by_tag = \"${image_base}:${hco_bundle_version}\"" -i $(params.CNV_VERSION)/payload.yaml - yq e ".hco_bundle_version = \"${hco_bundle_version}\"" -i $(params.CNV_VERSION)/payload.yaml - yq e ".version = null" -i $(params.CNV_VERSION)/payload.yaml - yq e ".releasePlan = null" -i $(params.CNV_VERSION)/payload.yaml + yq e ".hco_bundle_registry_by_tag = \"${image_base}:${hco_bundle_version}\"" -i ${save_folder}/payload.yaml + yq e ".hco_bundle_version = \"${hco_bundle_version}\"" -i ${save_folder}/payload.yaml + yq e ".version = null" -i ${save_folder}/payload.yaml + yq e ".releasePlan = null" -i ${save_folder}/payload.yaml git add . git commit -m "Update payload" From d0c8e3517d5ea652dcd45bc81a027efb1482d81b Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Thu, 30 Jan 2025 16:38:16 +0100 Subject: [PATCH 23/88] Temporarily hardcode version parameter Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index df4afa0..8e7be7d 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -79,7 +79,7 @@ spec: yq e ".snapshot_id = \"${snapshot_id}\"" -i ${save_folder}/payload.yaml yq e ".from_index = \"${from_index}\"" -i ${save_folder}/payload.yaml yq e ".fbc_fragment = \"${fbc_fragment}\"" -i ${save_folder}/payload.yaml - yq e ".channel = \"${channel}\"" -i ${save_folder}/payload.yaml + yq e ".channel = \"nightly\"" -i ${save_folder}/payload.yaml yq e ".hco_bundle_registry_by_sha = \"${image_sha}\"" -i ${save_folder}/payload.yaml image_base=$(echo "${image_sha}" | cut -d'@' -f1) yq e ".hco_bundle_registry_by_tag = \"${image_base}:${hco_bundle_version}\"" -i ${save_folder}/payload.yaml From 67271600dbac68207196b031985974da58e28d50 Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Thu, 30 Jan 2025 16:50:26 +0100 Subject: [PATCH 24/88] Change stages to lanes folder Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 8e7be7d..838dbf7 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -72,7 +72,7 @@ spec: git config --global user.name "${github_username}" git config --global user.email "no-reply@redhat.com" - save_folder="${cnv_version//./-}/stages/nightly/build" + save_folder="${cnv_version//./-}/lanes/nightly/build" mkdir -p "${save_folder}" echo "" > "${save_folder}/payload.yaml" yq e ".index_image = \"${index_image}\"" -i ${save_folder}/payload.yaml From 990246ec035db18ecbd59c6bc38d7910e4061250 Mon Sep 17 00:00:00 2001 From: Axuba Date: Fri, 31 Jan 2025 11:46:22 +0100 Subject: [PATCH 25/88] Channel folder to commit to will now depend on the fbc channel itself --- fbc/fbc-post-release.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 838dbf7..b2d8db1 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -72,14 +72,14 @@ spec: git config --global user.name "${github_username}" git config --global user.email "no-reply@redhat.com" - save_folder="${cnv_version//./-}/lanes/nightly/build" + save_folder="${cnv_version//./-}/lanes/${channel}/build" mkdir -p "${save_folder}" echo "" > "${save_folder}/payload.yaml" yq e ".index_image = \"${index_image}\"" -i ${save_folder}/payload.yaml yq e ".snapshot_id = \"${snapshot_id}\"" -i ${save_folder}/payload.yaml yq e ".from_index = \"${from_index}\"" -i ${save_folder}/payload.yaml yq e ".fbc_fragment = \"${fbc_fragment}\"" -i ${save_folder}/payload.yaml - yq e ".channel = \"nightly\"" -i ${save_folder}/payload.yaml + yq e ".channel = \"${channel}\"" -i ${save_folder}/payload.yaml yq e ".hco_bundle_registry_by_sha = \"${image_sha}\"" -i ${save_folder}/payload.yaml image_base=$(echo "${image_sha}" | cut -d'@' -f1) yq e ".hco_bundle_registry_by_tag = \"${image_base}:${hco_bundle_version}\"" -i ${save_folder}/payload.yaml From 4dbebd1e659567c53f001dd535010da4da001645 Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 6 Feb 2025 16:48:34 +0100 Subject: [PATCH 26/88] Update fbc-post-release.yaml --- fbc/fbc-post-release.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index b2d8db1..17458e1 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -86,6 +86,8 @@ spec: yq e ".hco_bundle_version = \"${hco_bundle_version}\"" -i ${save_folder}/payload.yaml yq e ".version = null" -i ${save_folder}/payload.yaml yq e ".releasePlan = null" -i ${save_folder}/payload.yaml + yq e ".freightName = null" -i ${save_folder}/payload.yaml + yq e ".freightID = null" -i ${save_folder}/payload.yaml git add . git commit -m "Update payload" From e12796d80d7130da68c47e76826dfcf993f45bc2 Mon Sep 17 00:00:00 2001 From: Tal Hason Date: Thu, 20 Feb 2025 16:58:53 +0200 Subject: [PATCH 27/88] added prNumber to the payload structure --- fbc/fbc-post-release.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 17458e1..95fdcb0 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -88,6 +88,7 @@ spec: yq e ".releasePlan = null" -i ${save_folder}/payload.yaml yq e ".freightName = null" -i ${save_folder}/payload.yaml yq e ".freightID = null" -i ${save_folder}/payload.yaml + yq e ".prNumber = null" -i ${save_folder}/payload.yaml git add . git commit -m "Update payload" From e1eed2153516ac18da5289e33acf33a3ea5ac7a9 Mon Sep 17 00:00:00 2001 From: Tal Hason Date: Sun, 2 Mar 2025 17:26:56 +0200 Subject: [PATCH 28/88] added minorVersion for kargo to use --- fbc/fbc-post-release.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 95fdcb0..8aa7700 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -84,6 +84,8 @@ spec: image_base=$(echo "${image_sha}" | cut -d'@' -f1) yq e ".hco_bundle_registry_by_tag = \"${image_base}:${hco_bundle_version}\"" -i ${save_folder}/payload.yaml yq e ".hco_bundle_version = \"${hco_bundle_version}\"" -i ${save_folder}/payload.yaml + # Add the minor version number from the bundle for Kargo + yq e '.minorVersion = (.hco_bundle_version | split("-") | .[0])' -i ${save_folder}/payload.yaml yq e ".version = null" -i ${save_folder}/payload.yaml yq e ".releasePlan = null" -i ${save_folder}/payload.yaml yq e ".freightName = null" -i ${save_folder}/payload.yaml From a3935a6c4c725b39bf145686efc803f80b05d1b6 Mon Sep 17 00:00:00 2001 From: Tal Hason Date: Tue, 18 Mar 2025 06:55:06 -0700 Subject: [PATCH 29/88] first release --- fbc/fbc-post-release.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 8aa7700..05662b6 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -91,6 +91,14 @@ spec: yq e ".freightName = null" -i ${save_folder}/payload.yaml yq e ".freightID = null" -i ${save_folder}/payload.yaml yq e ".prNumber = null" -i ${save_folder}/payload.yaml + # add a firstRelease flag to the payload + patch_version=$(echo "$hco_bundle_version" | grep -oP 'v\d+\.\d+\.\K\d+') + if [ "$patch_version" -eq 0 ]; then + yq -i '.firstRelease = true' ${save_folder}/payload.yaml + else + yq -i '.firstRelease = false' ${save_folder}/payload.yaml + fi + git add . git commit -m "Update payload" From 215bea291aa9d51a764f148e80fbf8cf42cfdece Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Fri, 28 Mar 2025 11:27:10 +0100 Subject: [PATCH 30/88] Separate v4.99 builds on fbc payloads Signed-off-by: Albert Jubany Juarez --- fbc/fbc-post-release.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 05662b6..8b80945 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -67,6 +67,10 @@ spec: channel=$(yq '.channel' ${cnv_version}/updated_image.yaml) hco_bundle_version=$(yq '.hco-bundle-version' ${cnv_version}/updated_image.yaml) + if [[ $hco_bundle_version == v4.99* ]]; then + cnv_version="v4.99" + fi + gitpayloaddir=$(mktemp -d) && cd "${gitpayloaddir}" git clone https://${github_token}@github.com/openshift-cnv/cnv-fbc-payloads.git && cd cnv-fbc-payloads git config --global user.name "${github_username}" From 4d9db25eda932d9dd4dc5db21291677839372920 Mon Sep 17 00:00:00 2001 From: Axuba Date: Wed, 4 Jun 2025 16:08:10 +0200 Subject: [PATCH 31/88] Add version, releaseplan and freightname data --- fbc/fbc-post-release.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 8b80945..fce6ca9 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -90,9 +90,9 @@ spec: yq e ".hco_bundle_version = \"${hco_bundle_version}\"" -i ${save_folder}/payload.yaml # Add the minor version number from the bundle for Kargo yq e '.minorVersion = (.hco_bundle_version | split("-") | .[0])' -i ${save_folder}/payload.yaml - yq e ".version = null" -i ${save_folder}/payload.yaml - yq e ".releasePlan = null" -i ${save_folder}/payload.yaml - yq e ".freightName = null" -i ${save_folder}/payload.yaml + yq e ".version = \"${cnv_version//./-}\"" -i ${save_folder}/payload.yaml + yq e ".releasePlan = \"stage\"" -i ${save_folder}/payload.yaml + yq e ".freightName = \"${snapshot_id}\"" -i ${save_folder}/payload.yaml yq e ".freightID = null" -i ${save_folder}/payload.yaml yq e ".prNumber = null" -i ${save_folder}/payload.yaml # add a firstRelease flag to the payload From 7c2fc9f2574ac6cce2df4cddde4dae578eb756a2 Mon Sep 17 00:00:00 2001 From: Axuba Date: Fri, 6 Jun 2025 09:58:54 +0200 Subject: [PATCH 32/88] Temporarily update repo --- fbc/fbc-post-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index fce6ca9..aa0eb67 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -72,7 +72,7 @@ spec: fi gitpayloaddir=$(mktemp -d) && cd "${gitpayloaddir}" - git clone https://${github_token}@github.com/openshift-cnv/cnv-fbc-payloads.git && cd cnv-fbc-payloads + git clone https://${github_token}@github.com/openshift-cnv/cnv-fbc-payloads-new.git && cd cnv-fbc-payloads git config --global user.name "${github_username}" git config --global user.email "no-reply@redhat.com" From 0b36a554f364ab82afb2fe1954af0bb68ac9e08d Mon Sep 17 00:00:00 2001 From: Axuba Date: Fri, 6 Jun 2025 11:33:36 +0200 Subject: [PATCH 33/88] Fix --- fbc/fbc-post-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index aa0eb67..1329400 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -72,7 +72,7 @@ spec: fi gitpayloaddir=$(mktemp -d) && cd "${gitpayloaddir}" - git clone https://${github_token}@github.com/openshift-cnv/cnv-fbc-payloads-new.git && cd cnv-fbc-payloads + git clone https://${github_token}@github.com/openshift-cnv/cnv-fbc-payloads-new.git && cd cnv-fbc-payloads-new git config --global user.name "${github_username}" git config --global user.email "no-reply@redhat.com" From d1e07c4ae7f6a66f67c6021fb394e7f011bc16f7 Mon Sep 17 00:00:00 2001 From: Axuba Date: Fri, 6 Jun 2025 11:47:43 +0200 Subject: [PATCH 34/88] Update fbc-post-release.yaml --- fbc/fbc-post-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 1329400..9b7bbee 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -76,7 +76,7 @@ spec: git config --global user.name "${github_username}" git config --global user.email "no-reply@redhat.com" - save_folder="${cnv_version//./-}/lanes/${channel}/build" + save_folder="${cnv_version//./-}/lanes/${channel}/stage" mkdir -p "${save_folder}" echo "" > "${save_folder}/payload.yaml" yq e ".index_image = \"${index_image}\"" -i ${save_folder}/payload.yaml From c29b04d288c1fd9ff4537b6bed07d01e01d1099f Mon Sep 17 00:00:00 2001 From: Tal Hason Date: Wed, 2 Jul 2025 02:08:30 -0400 Subject: [PATCH 35/88] Update fbc-post-release.yaml add hco_bundle_version to the commit message --- fbc/fbc-post-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 9b7bbee..1f273b0 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -105,5 +105,5 @@ spec: git add . - git commit -m "Update payload" + git commit -m "Update payload $hco_bundle_version" git push origin main From e4296d57d58242c0fe77391eaaf1014bdf1aaab1 Mon Sep 17 00:00:00 2001 From: Axuba Date: Tue, 15 Jul 2025 14:28:29 +0200 Subject: [PATCH 36/88] Add rhelVersion parameter --- fbc/fbc-post-release.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 1f273b0..ccb4c85 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -90,6 +90,7 @@ spec: yq e ".hco_bundle_version = \"${hco_bundle_version}\"" -i ${save_folder}/payload.yaml # Add the minor version number from the bundle for Kargo yq e '.minorVersion = (.hco_bundle_version | split("-") | .[0])' -i ${save_folder}/payload.yaml + yq e '.rhelVersion = (.minorVersion | split(".") | .[3])' -i ${save_folder}/payload.yaml yq e ".version = \"${cnv_version//./-}\"" -i ${save_folder}/payload.yaml yq e ".releasePlan = \"stage\"" -i ${save_folder}/payload.yaml yq e ".freightName = \"${snapshot_id}\"" -i ${save_folder}/payload.yaml From 1ed5ae73ed3db0872e7c50aaddaa151e8d42ccf3 Mon Sep 17 00:00:00 2001 From: Axuba Date: Mon, 25 Aug 2025 16:07:54 +0200 Subject: [PATCH 37/88] Add environment parameter --- fbc/fbc-post-release.yaml | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index ccb4c85..2bafecf 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -12,6 +12,8 @@ spec: type: string - name: releaseplan_id type: string + - name: environment + type: string tasks: - name: get-info params: @@ -21,6 +23,8 @@ spec: value: "$(params.cnv_version)" - name: RELEASEPLAN_ID value: "$(params.releaseplan_id)" + - name: ENVIRONMENT + value: "$(params.ENVIRONMENT)" taskSpec: params: - name: SNAPSHOT @@ -29,6 +33,8 @@ spec: type: string - name: RELEASEPLAN_ID type: string + - name: ENVIRONMENT + type: string steps: - name: get-info image: quay.io/konflux-ci/release-service-utils:0a58b6a6b562879e89395636d97931f2dcbb494c @@ -76,7 +82,19 @@ spec: git config --global user.name "${github_username}" git config --global user.email "no-reply@redhat.com" - save_folder="${cnv_version//./-}/lanes/${channel}/stage" + case $(params.ENVIRONMENT) in + "production") + NEXT_STAGE="verify-production-release" + ;; + "stage") + NEXT_STAGE="stage" + ;; + *) + echo "Unknown environment: $(params.ENVIRONMENT)" + exit 1 + ;; + esac + save_folder="${cnv_version//./-}/lanes/${channel}/${NEXT_STAGE}" mkdir -p "${save_folder}" echo "" > "${save_folder}/payload.yaml" yq e ".index_image = \"${index_image}\"" -i ${save_folder}/payload.yaml @@ -92,7 +110,7 @@ spec: yq e '.minorVersion = (.hco_bundle_version | split("-") | .[0])' -i ${save_folder}/payload.yaml yq e '.rhelVersion = (.minorVersion | split(".") | .[3])' -i ${save_folder}/payload.yaml yq e ".version = \"${cnv_version//./-}\"" -i ${save_folder}/payload.yaml - yq e ".releasePlan = \"stage\"" -i ${save_folder}/payload.yaml + yq e ".releasePlan = \"${NEXT_STAGE}\"" -i ${save_folder}/payload.yaml yq e ".freightName = \"${snapshot_id}\"" -i ${save_folder}/payload.yaml yq e ".freightID = null" -i ${save_folder}/payload.yaml yq e ".prNumber = null" -i ${save_folder}/payload.yaml From cc4c615cf53a98092d64e8e1082564c6d34006cf Mon Sep 17 00:00:00 2001 From: Axuba Date: Mon, 25 Aug 2025 17:45:50 +0200 Subject: [PATCH 38/88] Fix typo --- fbc/fbc-post-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 2bafecf..0f3dd35 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -24,7 +24,7 @@ spec: - name: RELEASEPLAN_ID value: "$(params.releaseplan_id)" - name: ENVIRONMENT - value: "$(params.ENVIRONMENT)" + value: "$(params.environment)" taskSpec: params: - name: SNAPSHOT From 2e64cc5529e8460dbb61f636aa47c4f2532da170 Mon Sep 17 00:00:00 2001 From: Axuba Date: Wed, 26 Nov 2025 16:55:57 +0100 Subject: [PATCH 39/88] Add update-bundle pipeline (#8) --- pipelines/update-bundle.yaml | 59 ++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 pipelines/update-bundle.yaml diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml new file mode 100644 index 0000000..9a02dc2 --- /dev/null +++ b/pipelines/update-bundle.yaml @@ -0,0 +1,59 @@ +--- +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + name: update-bundle +spec: + description: This tasks gets all the required data of an FBC build and commits it to a payload repository to be used in a GitOps environment. + params: + - name: snapshot + type: string + tasks: + - name: update-bundle + params: + - name: SNAPSHOT + value: "$(params.snapshot)" + taskSpec: + params: + - name: SNAPSHOT + type: string + steps: + - name: update-bundle + image: quay.io/konflux-ci/release-service-utils@sha256:ab9fce5bf41c15f1475d660da302f935e0999143ef4c50606846b189cb742caf + envFrom: + - secretRef: + name: hco-updater-gitlab-token + script: | + #!/usr/bin/env bash + set -eo pipefail + + SNAPSHOT_ID=$(echo "$(params.SNAPSHOT)" | awk -F'/' '{print $2}') + SNAPSHOT_DATA=$(kubectl get snapshot $SNAPSHOT_ID -ojson) + NAMESPACE=$(jq -r '.metadata.namespace' <<< "$SNAPSHOT_DATA") + VERSION=$(echo "$NAMESPACE" | cut -d'-' -f1,2) + REPO_URL="https://gitlab.cee.redhat.com/openshift-virtualization/konflux-builds/${VERSION}/hco-bundle-registry.git" + + git clone $REPO_URL --depth 1 + cd hco-bundle-registry + AUTH_REPO_URL=$(echo "$REPO_URL" | sed "s|https://|https://oauth2:${GITLAB_TOKEN}@|") + git remote set-url origin "$AUTH_REPO_URL" + git config user.name "submodule-sync" + git config user.email "no-reply@redhat.com" + + IMAGES=$(jq -r '.spec.components[].containerImage' <<< "$SNAPSHOT_DATA") + for img in $IMAGES; do + image_name_sha=$(echo "${img##*/}") + image_name=$(echo "$image_name_sha" | cut -d'@' -f1) + + if [[ "$image_name" == *"-operator" ]]; then + json_file="components/hco-bundle-registry/core-params.json" + else + json_file="components/hco-bundle-registry/extra-params.json" + fi + jq ".\"${image_name}-image\" = \"${image_name_sha}\"" "$json_file" > "${json_file}.tmp" && mv "${json_file}.tmp" "$json_file" + done + + git add . + git commit -m "Update HCO bundle registry with new images" + git pull --rebase origin main + git push origin main From 3e36af39b0bf7b01055811f7411882bd0e8f88af Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Wed, 26 Nov 2025 17:40:32 +0100 Subject: [PATCH 40/88] Pull with creds Signed-off-by: Albert Jubany Juarez --- pipelines/update-bundle.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 9a02dc2..1769ab5 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -32,11 +32,11 @@ spec: NAMESPACE=$(jq -r '.metadata.namespace' <<< "$SNAPSHOT_DATA") VERSION=$(echo "$NAMESPACE" | cut -d'-' -f1,2) REPO_URL="https://gitlab.cee.redhat.com/openshift-virtualization/konflux-builds/${VERSION}/hco-bundle-registry.git" + REPO_URL=$(echo "$REPO_URL" | sed "s|https://|https://oauth2:${GITLAB_TOKEN}@|") git clone $REPO_URL --depth 1 cd hco-bundle-registry - AUTH_REPO_URL=$(echo "$REPO_URL" | sed "s|https://|https://oauth2:${GITLAB_TOKEN}@|") - git remote set-url origin "$AUTH_REPO_URL" + git remote set-url origin "$REPO_URL" git config user.name "submodule-sync" git config user.email "no-reply@redhat.com" From d12c626448808fd76eadd880fd8d6fa01818035b Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 27 Nov 2025 11:07:54 +0100 Subject: [PATCH 41/88] Make sure all the commits in every component are the same --- pipelines/update-bundle.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 1769ab5..416987a 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -41,6 +41,15 @@ spec: git config user.email "no-reply@redhat.com" IMAGES=$(jq -r '.spec.components[].containerImage' <<< "$SNAPSHOT_DATA") + + # Make sure all the commits in every component are the same + if jq -e '[.spec.components[].source.git.revision] | unique | length == 1' <<< "$SNAPSHOT_DATA" > /dev/null; then + echo "The snapshot has all the components pointing to the same commit, continuing." + else + echo "Commits are inconsistent!" + exit 1 + fi + for img in $IMAGES; do image_name_sha=$(echo "${img##*/}") image_name=$(echo "$image_name_sha" | cut -d'@' -f1) From 53553ee008d60919a393694a7cf67e4518c87f15 Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 27 Nov 2025 15:34:18 +0100 Subject: [PATCH 42/88] Fix IIB status path as it changed --- fbc/fbc-post-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 0f3dd35..e663a5d 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -59,7 +59,7 @@ spec: cnv_version="$(params.CNV_VERSION)" snapshot_data=$(kubectl get snapshot "${snapshot_id}" -oyaml) fbc_fragment=$(echo "${snapshot_data}" | yq '.spec.components[0].containerImage') - index_image=$(kubectl get release "${release_id}" -oyaml | yq '.status.artifacts.index_image.index_image') + index_image=$(kubectl get release "${release_id}" -oyaml | yq ".status.artifacts.index_image.\"${cnv_version}\".index_image") from_index="registry-proxy.engineering.redhat.com/rh-osbs/iib-pub-pending:${cnv_version}" git_commit=$(echo "${snapshot_data}" | yq '.spec.components[0].source.git.revision') From 2297da5a30c04e0d7f411fd02fa496bf5278e9c8 Mon Sep 17 00:00:00 2001 From: Axuba Date: Wed, 10 Dec 2025 09:08:18 +0100 Subject: [PATCH 43/88] Fix operator check as now it includes -rhel suffix --- pipelines/update-bundle.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 416987a..526fc30 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -54,7 +54,7 @@ spec: image_name_sha=$(echo "${img##*/}") image_name=$(echo "$image_name_sha" | cut -d'@' -f1) - if [[ "$image_name" == *"-operator" ]]; then + if [[ "$image_name" == *"-operator-"* ]]; then json_file="components/hco-bundle-registry/core-params.json" else json_file="components/hco-bundle-registry/extra-params.json" From 545e7e33341b73c4d10be4fe83596d446ebd222a Mon Sep 17 00:00:00 2001 From: Axuba Date: Wed, 10 Dec 2025 09:10:52 +0100 Subject: [PATCH 44/88] Another fix so test images dont go to core params --- pipelines/update-bundle.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 526fc30..8ff7571 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -54,7 +54,7 @@ spec: image_name_sha=$(echo "${img##*/}") image_name=$(echo "$image_name_sha" | cut -d'@' -f1) - if [[ "$image_name" == *"-operator-"* ]]; then + if [[ "$image_name" == *"-operator-rhel"* ]]; then json_file="components/hco-bundle-registry/core-params.json" else json_file="components/hco-bundle-registry/extra-params.json" From 7847dd72e239093754c4199d47238057796102ad Mon Sep 17 00:00:00 2001 From: Axuba Date: Mon, 22 Dec 2025 11:25:48 +0100 Subject: [PATCH 45/88] Add snapshot id to a new snapshots json file --- pipelines/update-bundle.yaml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 8ff7571..a9db9a7 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -30,6 +30,7 @@ spec: SNAPSHOT_ID=$(echo "$(params.SNAPSHOT)" | awk -F'/' '{print $2}') SNAPSHOT_DATA=$(kubectl get snapshot $SNAPSHOT_ID -ojson) NAMESPACE=$(jq -r '.metadata.namespace' <<< "$SNAPSHOT_DATA") + APPLICATION=$(jq -r '.spec.application' <<< "$SNAPSHOT_DATA") VERSION=$(echo "$NAMESPACE" | cut -d'-' -f1,2) REPO_URL="https://gitlab.cee.redhat.com/openshift-virtualization/konflux-builds/${VERSION}/hco-bundle-registry.git" REPO_URL=$(echo "$REPO_URL" | sed "s|https://|https://oauth2:${GITLAB_TOKEN}@|") @@ -62,6 +63,16 @@ spec: jq ".\"${image_name}-image\" = \"${image_name_sha}\"" "$json_file" > "${json_file}.tmp" && mv "${json_file}.tmp" "$json_file" done + snapshots_file="components/hco-bundle-registry/snapshots.json" + touch ${snapshots_file} + jq -n \ + --slurpfile f "$snapshots_file" \ + --arg app "$APPLICATION" \ + --arg snap "$SNAPSHOT_ID" \ + '$f[0] // {} | .[$app] = $snap' \ + > "$snapshots_file.tmp" \ + && mv "$snapshots_file.tmp" "$snapshots_file" + git add . git commit -m "Update HCO bundle registry with new images" git pull --rebase origin main From bc659e848dd1c007154e31d4d4dfbda7564b4128 Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 8 Jan 2026 09:33:18 +0100 Subject: [PATCH 46/88] Push release skeleton for hco-bundle-images (#9) Signed-off-by: Albert Jubany Juarez --- pipelines/update-bundle.yaml | 117 ++++++++++++++++++++++++++++------- 1 file changed, 95 insertions(+), 22 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index a9db9a7..59160f9 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -17,9 +17,18 @@ spec: params: - name: SNAPSHOT type: string + results: + - name: snapshots-to-release + description: Contents of the snapshots.json file + - name: bundle-version + description: NVR of the bundle + volumes: + - name: quay-creds + secret: + secretName: quay-builds-creds steps: - name: update-bundle - image: quay.io/konflux-ci/release-service-utils@sha256:ab9fce5bf41c15f1475d660da302f935e0999143ef4c50606846b189cb742caf + image: quay.io/konflux-ci/release-service-utils@sha256:2f9e6863e82bbc9ddce5a290f3fd0e87657c475e3de8a832b2ef7f8d0671e7d3 envFrom: - secretRef: name: hco-updater-gitlab-token @@ -51,29 +60,93 @@ spec: exit 1 fi - for img in $IMAGES; do - image_name_sha=$(echo "${img##*/}") - image_name=$(echo "$image_name_sha" | cut -d'@' -f1) - - if [[ "$image_name" == *"-operator-rhel"* ]]; then - json_file="components/hco-bundle-registry/core-params.json" - else - json_file="components/hco-bundle-registry/extra-params.json" - fi - jq ".\"${image_name}-image\" = \"${image_name_sha}\"" "$json_file" > "${json_file}.tmp" && mv "${json_file}.tmp" "$json_file" - done - - snapshots_file="components/hco-bundle-registry/snapshots.json" - touch ${snapshots_file} - jq -n \ - --slurpfile f "$snapshots_file" \ - --arg app "$APPLICATION" \ - --arg snap "$SNAPSHOT_ID" \ - '$f[0] // {} | .[$app] = $snap' \ - > "$snapshots_file.tmp" \ - && mv "$snapshots_file.tmp" "$snapshots_file" + function update_images_snapshots() { + for img in $IMAGES; do + image_name_sha=$(echo "${img##*/}") + image_name=$(echo "$image_name_sha" | cut -d'@' -f1) + + if [[ "$image_name" == *"-operator-rhel"* ]]; then + json_file="components/hco-bundle-registry/core-params.json" + else + json_file="components/hco-bundle-registry/extra-params.json" + fi + jq ".\"${image_name}-image\" = \"${image_name_sha}\"" "$json_file" > "${json_file}.tmp" && mv "${json_file}.tmp" "$json_file" + done + + snapshots_file="components/hco-bundle-registry/snapshots.json" + touch ${snapshots_file} + jq -n \ + --slurpfile f "$snapshots_file" \ + --arg app "$APPLICATION" \ + --arg snap "$SNAPSHOT_ID" \ + '$f[0] // {} | .[$app] = $snap' \ + > "$snapshots_file.tmp" \ + && mv "$snapshots_file.tmp" "$snapshots_file" + } + + update_images_snapshots git add . git commit -m "Update HCO bundle registry with new images" git pull --rebase origin main git push origin main + + if [[ "$(params.SNAPSHOT)" == *"hco-bundle-registry"* ]]; then + REPO_REVISION=$(jq -r '.spec.components[].source.git.revision' <<< "$SNAPSHOT_DATA") + + BUNDLE_VERSION=$(cat build-bundle.json | jq -r '.metadata.Version | "\(.XY).\(.Z)-\(.release)" | sub("^v"; "")') + echo -n "$BUNDLE_VERSION" > /tekton/results/bundle-version + + # Make sure we are getting the exact snapshots from the bundle + git checkout $REPO_REVISION + + # Update the bundle snapshot as its not updated in this commit + update_images_snapshots + + SNAPSHOTS_TO_RELEASE=$(cat $snapshots_file) + echo -n "$SNAPSHOTS_TO_RELEASE" > /tekton/results/snapshots-to-release + fi + - name: push-release-chart + image: quay.io/konflux-ci/release-service-utils@sha256:2f9e6863e82bbc9ddce5a290f3fd0e87657c475e3de8a832b2ef7f8d0671e7d3 + envFrom: + - secretRef: + name: hco-updater-gitlab-token + - secretRef: + name: quay-builds-creds + volumeMounts: + - name: quay-creds + mountPath: /tekton/secrets/quay-builds-creds + readOnly: true + script: | + #!/usr/bin/env bash + set -eo pipefail + + # Only continue if its releasing hco-bundle-registry + if [[ "$(params.SNAPSHOT)" != *"hco-bundle-registry"* ]]; then + echo "Skipping push-release-chart: snapshot parameter does not contain 'hco-bundle-registry'" + exit 0 + fi + + # Read results from previous step + SNAPSHOTS_TO_RELEASE=$(cat /tekton/results/snapshots-to-release) + BUNDLE_VERSION=$(cat /tekton/results/bundle-version) + + git clone https://gitlab.cee.redhat.com/openshift-virtualization/konflux-builds/release-chart.git --depth 1 + cd release-chart/release-orchestrator + yq -i ".version = \"$BUNDLE_VERSION-skeleton\"" Chart.yaml + + # Update values.yaml with snapshots from SNAPSHOTS_TO_RELEASE + echo "$SNAPSHOTS_TO_RELEASE" | jq -r '{snapshots: .}' | yq eval -P '.' > /tmp/snapshots_with_key.yaml + yq eval-all '. as $item ireduce ({}; . * $item)' values.yaml /tmp/snapshots_with_key.yaml -i + + DOCKER_CONFIG=$(cat /tekton/secrets/quay-builds-creds/.dockerconfigjson) + QUAY_USERNAME=$(echo "${DOCKER_CONFIG}" | jq -r '.auths | to_entries[] | select(.key | contains("quay.io")) | .value.username') + QUAY_PASSWORD=$(echo "${DOCKER_CONFIG}" | jq -r '.auths | to_entries[] | select(.key | contains("quay.io")) | .value.password') + QUAY_URL=$(echo "${DOCKER_CONFIG}" | jq -r '.auths | to_entries[] | .key') + + echo "${QUAY_PASSWORD}" | helm registry login quay.io --username "${QUAY_USERNAME}" --password-stdin + + PACKAGE_OUTPUT=$(helm package . 2>&1) + PACKAGE_FILE=$(echo "${PACKAGE_OUTPUT}" | grep -oP 'Successfully packaged chart and saved it to: \K.*') + + helm push $PACKAGE_FILE oci://${QUAY_URL}/release-orchestrator From ac16481b76653274399dd06f1446da2dc99bca6f Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 8 Jan 2026 10:01:02 +0100 Subject: [PATCH 47/88] Use tmp for quay build creds path --- pipelines/update-bundle.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 59160f9..ffcc2ff 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -115,7 +115,7 @@ spec: name: quay-builds-creds volumeMounts: - name: quay-creds - mountPath: /tekton/secrets/quay-builds-creds + mountPath: /tmp/quay-builds-creds readOnly: true script: | #!/usr/bin/env bash @@ -139,7 +139,7 @@ spec: echo "$SNAPSHOTS_TO_RELEASE" | jq -r '{snapshots: .}' | yq eval -P '.' > /tmp/snapshots_with_key.yaml yq eval-all '. as $item ireduce ({}; . * $item)' values.yaml /tmp/snapshots_with_key.yaml -i - DOCKER_CONFIG=$(cat /tekton/secrets/quay-builds-creds/.dockerconfigjson) + DOCKER_CONFIG=$(cat /tmp/quay-builds-creds/.dockerconfigjson) QUAY_USERNAME=$(echo "${DOCKER_CONFIG}" | jq -r '.auths | to_entries[] | select(.key | contains("quay.io")) | .value.username') QUAY_PASSWORD=$(echo "${DOCKER_CONFIG}" | jq -r '.auths | to_entries[] | select(.key | contains("quay.io")) | .value.password') QUAY_URL=$(echo "${DOCKER_CONFIG}" | jq -r '.auths | to_entries[] | .key') From adb0e6eb749a4c7fcf318fbdbd2bf86943e79b75 Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 8 Jan 2026 10:35:55 +0100 Subject: [PATCH 48/88] Use pipeline tools image to push the chart --- pipelines/update-bundle.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index ffcc2ff..6fa640f 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -107,7 +107,7 @@ spec: echo -n "$SNAPSHOTS_TO_RELEASE" > /tekton/results/snapshots-to-release fi - name: push-release-chart - image: quay.io/konflux-ci/release-service-utils@sha256:2f9e6863e82bbc9ddce5a290f3fd0e87657c475e3de8a832b2ef7f8d0671e7d3 + image: quay.io/redhat-user-workloads/ocp-virt-images-tenant/pipeline-tools@sha256:18f9f819e9393891ce7ae19414a5672786e3efb120bdeaa2c254d8ba5d8e2493 envFrom: - secretRef: name: hco-updater-gitlab-token From 38c121bd7ce526a773279189f88cedb6734a8ec3 Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 8 Jan 2026 10:42:29 +0100 Subject: [PATCH 49/88] Check if there are actually changes before committing --- pipelines/update-bundle.yaml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 6fa640f..24a2b4a 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -87,9 +87,14 @@ spec: update_images_snapshots git add . - git commit -m "Update HCO bundle registry with new images" - git pull --rebase origin main - git push origin main + # Check if there are actually changes before committing + if ! git diff-index --quiet HEAD; then + git commit -m "Update HCO bundle registry with new images" + git pull --rebase origin main + git push origin main + else + echo "No changes detected in the bundle registry. Skipping git push." + fi if [[ "$(params.SNAPSHOT)" == *"hco-bundle-registry"* ]]; then REPO_REVISION=$(jq -r '.spec.components[].source.git.revision' <<< "$SNAPSHOT_DATA") From b4e410cd02136555111d9882fcc15042c0a765fb Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 8 Jan 2026 10:45:30 +0100 Subject: [PATCH 50/88] Increase clone depth --- pipelines/update-bundle.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 24a2b4a..acb3848 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -44,7 +44,7 @@ spec: REPO_URL="https://gitlab.cee.redhat.com/openshift-virtualization/konflux-builds/${VERSION}/hco-bundle-registry.git" REPO_URL=$(echo "$REPO_URL" | sed "s|https://|https://oauth2:${GITLAB_TOKEN}@|") - git clone $REPO_URL --depth 1 + git clone $REPO_URL --depth 50 cd hco-bundle-registry git remote set-url origin "$REPO_URL" git config user.name "submodule-sync" From 800354360d6fbaf8106a0350ef929c60b097f5a8 Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 8 Jan 2026 10:48:43 +0100 Subject: [PATCH 51/88] Work under a tmpdir --- pipelines/update-bundle.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index acb3848..a4dd194 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -124,7 +124,7 @@ spec: readOnly: true script: | #!/usr/bin/env bash - set -eo pipefail + set -exo pipefail # Only continue if its releasing hco-bundle-registry if [[ "$(params.SNAPSHOT)" != *"hco-bundle-registry"* ]]; then @@ -136,6 +136,8 @@ spec: SNAPSHOTS_TO_RELEASE=$(cat /tekton/results/snapshots-to-release) BUNDLE_VERSION=$(cat /tekton/results/bundle-version) + TMPDIR=$(mktemp -d) + cd "$TMPDIR" git clone https://gitlab.cee.redhat.com/openshift-virtualization/konflux-builds/release-chart.git --depth 1 cd release-chart/release-orchestrator yq -i ".version = \"$BUNDLE_VERSION-skeleton\"" Chart.yaml From ce791e221054da684f5af9f1663bf3ba05571196 Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 8 Jan 2026 10:51:36 +0100 Subject: [PATCH 52/88] Use tmp as home, instead of default / --- pipelines/update-bundle.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index a4dd194..8fb9212 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -138,6 +138,7 @@ spec: TMPDIR=$(mktemp -d) cd "$TMPDIR" + export HOME=/tmp git clone https://gitlab.cee.redhat.com/openshift-virtualization/konflux-builds/release-chart.git --depth 1 cd release-chart/release-orchestrator yq -i ".version = \"$BUNDLE_VERSION-skeleton\"" Chart.yaml From 28d5b62e77a2e51e129d9cf5d196bacd7f9674a4 Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 8 Jan 2026 11:21:13 +0100 Subject: [PATCH 53/88] Fix quay url --- pipelines/update-bundle.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 8fb9212..9f5c78c 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -124,7 +124,7 @@ spec: readOnly: true script: | #!/usr/bin/env bash - set -exo pipefail + set -eo pipefail # Only continue if its releasing hco-bundle-registry if [[ "$(params.SNAPSHOT)" != *"hco-bundle-registry"* ]]; then @@ -157,4 +157,4 @@ spec: PACKAGE_OUTPUT=$(helm package . 2>&1) PACKAGE_FILE=$(echo "${PACKAGE_OUTPUT}" | grep -oP 'Successfully packaged chart and saved it to: \K.*') - helm push $PACKAGE_FILE oci://${QUAY_URL}/release-orchestrator + helm push $PACKAGE_FILE oci://${QUAY_URL} From 7f6c73aa8613c790eb2cd1da3643485f4ee340b7 Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 8 Jan 2026 11:28:52 +0100 Subject: [PATCH 54/88] Fill releaseplan and namespace --- pipelines/update-bundle.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 9f5c78c..fa4a8f4 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -135,13 +135,16 @@ spec: # Read results from previous step SNAPSHOTS_TO_RELEASE=$(cat /tekton/results/snapshots-to-release) BUNDLE_VERSION=$(cat /tekton/results/bundle-version) + XY=$(echo "$BUNDLE_VERSION" | cut -d'.' -f1,2 | tr '.' '-') TMPDIR=$(mktemp -d) cd "$TMPDIR" export HOME=/tmp git clone https://gitlab.cee.redhat.com/openshift-virtualization/konflux-builds/release-chart.git --depth 1 cd release-chart/release-orchestrator - yq -i ".version = \"$BUNDLE_VERSION-skeleton\"" Chart.yaml + yq -i ".version = \"$BUNDLE_VERSION\"" Chart.yaml + yq -i ".global.releasePlan = \"TODO-RELEASEPLAN\"" + yq -i ".global.targetNamespace = \"v${XY}-openshift-virtualization-tenant\"" # Update values.yaml with snapshots from SNAPSHOTS_TO_RELEASE echo "$SNAPSHOTS_TO_RELEASE" | jq -r '{snapshots: .}' | yq eval -P '.' > /tmp/snapshots_with_key.yaml From 0b30634186445379793263e75592f29ce69668d5 Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 8 Jan 2026 11:30:11 +0100 Subject: [PATCH 55/88] Fix --- pipelines/update-bundle.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index fa4a8f4..57746e1 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -143,8 +143,8 @@ spec: git clone https://gitlab.cee.redhat.com/openshift-virtualization/konflux-builds/release-chart.git --depth 1 cd release-chart/release-orchestrator yq -i ".version = \"$BUNDLE_VERSION\"" Chart.yaml - yq -i ".global.releasePlan = \"TODO-RELEASEPLAN\"" - yq -i ".global.targetNamespace = \"v${XY}-openshift-virtualization-tenant\"" + yq -i ".global.releasePlan = \"TODO-RELEASEPLAN\"" Chart.yaml + yq -i ".global.targetNamespace = \"v${XY}-openshift-virtualization-tenant\"" Chart.yaml # Update values.yaml with snapshots from SNAPSHOTS_TO_RELEASE echo "$SNAPSHOTS_TO_RELEASE" | jq -r '{snapshots: .}' | yq eval -P '.' > /tmp/snapshots_with_key.yaml From 05da569534efdb4178b50dfd41940c8dacae67cb Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 8 Jan 2026 11:33:32 +0100 Subject: [PATCH 56/88] Fix typo --- pipelines/update-bundle.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 57746e1..0a14eaf 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -143,8 +143,8 @@ spec: git clone https://gitlab.cee.redhat.com/openshift-virtualization/konflux-builds/release-chart.git --depth 1 cd release-chart/release-orchestrator yq -i ".version = \"$BUNDLE_VERSION\"" Chart.yaml - yq -i ".global.releasePlan = \"TODO-RELEASEPLAN\"" Chart.yaml - yq -i ".global.targetNamespace = \"v${XY}-openshift-virtualization-tenant\"" Chart.yaml + yq -i ".global.releasePlan = \"TODO-RELEASEPLAN\"" values.yaml + yq -i ".global.targetNamespace = \"v${XY}-openshift-virtualization-tenant\"" values.yaml # Update values.yaml with snapshots from SNAPSHOTS_TO_RELEASE echo "$SNAPSHOTS_TO_RELEASE" | jq -r '{snapshots: .}' | yq eval -P '.' > /tmp/snapshots_with_key.yaml From 98e6950d6a36268744269cccb14f048f44998503 Mon Sep 17 00:00:00 2001 From: Axuba Date: Mon, 12 Jan 2026 15:11:11 +0100 Subject: [PATCH 57/88] Add hco bundle url to payload --- fbc/fbc-post-release.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index e663a5d..3032b68 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -72,6 +72,7 @@ spec: image_sha=$(yq '.image' ${cnv_version}/updated_image.yaml) channel=$(yq '.channel' ${cnv_version}/updated_image.yaml) hco_bundle_version=$(yq '.hco-bundle-version' ${cnv_version}/updated_image.yaml) + hco_bundle_url=$(yq '.hco-bundle-url' ${cnv_version}/updated_image.yaml) if [[ $hco_bundle_version == v4.99* ]]; then cnv_version="v4.99" @@ -106,6 +107,7 @@ spec: image_base=$(echo "${image_sha}" | cut -d'@' -f1) yq e ".hco_bundle_registry_by_tag = \"${image_base}:${hco_bundle_version}\"" -i ${save_folder}/payload.yaml yq e ".hco_bundle_version = \"${hco_bundle_version}\"" -i ${save_folder}/payload.yaml + yq e ".hco_bundle_url = \"${hco_bundle_url}\"" -i ${save_folder}/payload.yaml # Add the minor version number from the bundle for Kargo yq e '.minorVersion = (.hco_bundle_version | split("-") | .[0])' -i ${save_folder}/payload.yaml yq e '.rhelVersion = (.minorVersion | split(".") | .[3])' -i ${save_folder}/payload.yaml From 82e75a0cb8191e4006db52574ddcb71c58ee2ea1 Mon Sep 17 00:00:00 2001 From: thason Date: Tue, 20 Jan 2026 16:36:18 +0200 Subject: [PATCH 58/88] Add skeleton chart version parameter to update-bundle pipeline and document pipelines in README --- fbc/fbc-post-release.yaml | 1 + pipelines/README.md | 69 +++++++++++++++++++++++++++++++++++ pipelines/update-bundle.yaml | 71 +++++++++++++++++++++++++++++------- 3 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 pipelines/README.md diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 3032b68..81e38a0 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -79,6 +79,7 @@ spec: fi gitpayloaddir=$(mktemp -d) && cd "${gitpayloaddir}" + # github_token and github_username are injected from cnv-ci-release-token secret git clone https://${github_token}@github.com/openshift-cnv/cnv-fbc-payloads-new.git && cd cnv-fbc-payloads-new git config --global user.name "${github_username}" git config --global user.email "no-reply@redhat.com" diff --git a/pipelines/README.md b/pipelines/README.md new file mode 100644 index 0000000..11b3354 --- /dev/null +++ b/pipelines/README.md @@ -0,0 +1,69 @@ +# CNV Tekton Pipelines + +Tekton pipelines for CNV component builds and releases in Konflux. + +## Pipelines + +### update-bundle + +Updates the HCO bundle registry with component snapshots and publishes the release orchestrator chart. + +**Trigger:** Runs when a component snapshot is created for `hco-bundle-registry`. + +**Parameters:** + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `snapshot` | string | Yes | — | Snapshot reference (e.g., `namespace/snapshot-id`) | +| `skeleton-chart-version` | string | No | `0.0.0-skeleton` | Version of skeleton chart to pull from OCI registry | + +**Steps:** + +1. **update-bundle**: Updates `hco-bundle-registry` GitLab repo with component image references +2. **push-release-chart**: Pulls skeleton chart, hydrates with snapshots, and pushes versioned chart + +**Secrets Required:** + +| Secret | Keys | Purpose | +|--------|------|---------| +| `hco-updater-gitlab-token` | `GITLAB_TOKEN` | GitLab repo access | +| `quay-builds-creds` | `.dockerconfigjson` | OCI registry push | + +**Outputs:** + +- `bundle-version`: Version string (e.g., `4.99.0-rhel9.2555`) +- `snapshots-to-release`: JSON map of component → snapshot ID + +**Version Format:** + +``` +Input: build-bundle.json { XY: "v4.99", Z: "0", os: "rhel9", release: "2555" } +Output: 4.99.0-rhel9.2555 +``` + +**Dual ReleasePlan:** + +The pipeline sets two ReleasePlans in the chart: +- `releasePlan`: For regular components (kubevirt, cdi, etc.) +- `bundleReleasePlan`: For `hco-bundle-registry` (separate Konflux pipeline) + +--- + +## Development + +### Testing Locally + +The pipelines require Konflux cluster access. For local validation: + +```bash +# Validate YAML syntax +kubectl apply --dry-run=client -f pipelines/update-bundle.yaml +``` + +### Required Tools in Pipeline Images + +- `kubectl` - Kubernetes API access +- `jq` - JSON processing +- `yq` - YAML processing +- `helm` (v3.x) - Chart operations +- `git` - Repository operations diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 0a14eaf..9cbc7a4 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -8,15 +8,22 @@ spec: params: - name: snapshot type: string + - name: skeleton-chart-version + type: string + default: "0.0.0-skeleton" tasks: - name: update-bundle params: - name: SNAPSHOT value: "$(params.snapshot)" + - name: SKELETON_CHART_VERSION + value: "$(params.skeleton-chart-version)" taskSpec: params: - name: SNAPSHOT type: string + - name: SKELETON_CHART_VERSION + type: string results: - name: snapshots-to-release description: Contents of the snapshots.json file @@ -97,9 +104,10 @@ spec: fi if [[ "$(params.SNAPSHOT)" == *"hco-bundle-registry"* ]]; then - REPO_REVISION=$(jq -r '.spec.components[].source.git.revision' <<< "$SNAPSHOT_DATA") + # Use [0] to get single value (all components have same revision, validated above) + REPO_REVISION=$(jq -r '.spec.components[0].source.git.revision' <<< "$SNAPSHOT_DATA") - BUNDLE_VERSION=$(cat build-bundle.json | jq -r '.metadata.Version | "\(.XY).\(.Z)-\(.release)" | sub("^v"; "")') + BUNDLE_VERSION=$(cat build-bundle.json | jq -r '.metadata.Version | "\(.XY).\(.Z)-\(.os).\(.release)" | sub("^v"; "")') echo -n "$BUNDLE_VERSION" > /tekton/results/bundle-version # Make sure we are getting the exact snapshots from the bundle @@ -132,6 +140,10 @@ spec: exit 0 fi + # Configuration + OCI_REGISTRY="quay.io/openshift-virtualization/release-chart" + SKELETON_VERSION="$(params.SKELETON_CHART_VERSION)" + # Read results from previous step SNAPSHOTS_TO_RELEASE=$(cat /tekton/results/snapshots-to-release) BUNDLE_VERSION=$(cat /tekton/results/bundle-version) @@ -140,24 +152,55 @@ spec: TMPDIR=$(mktemp -d) cd "$TMPDIR" export HOME=/tmp - git clone https://gitlab.cee.redhat.com/openshift-virtualization/konflux-builds/release-chart.git --depth 1 - cd release-chart/release-orchestrator - yq -i ".version = \"$BUNDLE_VERSION\"" Chart.yaml - yq -i ".global.releasePlan = \"TODO-RELEASEPLAN\"" values.yaml + + # Registry login - extract first matching quay.io credentials + DOCKER_CONFIG=$(cat /tmp/quay-builds-creds/.dockerconfigjson) + QUAY_USERNAME=$(echo "${DOCKER_CONFIG}" | jq -r '[.auths | to_entries[] | select(.key | contains("quay.io"))] | first | .value.username') + QUAY_PASSWORD=$(echo "${DOCKER_CONFIG}" | jq -r '[.auths | to_entries[] | select(.key | contains("quay.io"))] | first | .value.password') + + if [[ -z "${QUAY_USERNAME}" || "${QUAY_USERNAME}" == "null" ]]; then + echo "ERROR: Could not extract quay.io credentials from secret" + exit 1 + fi + + echo "${QUAY_PASSWORD}" | helm registry login quay.io --username "${QUAY_USERNAME}" --password-stdin + + # Pull skeleton chart from OCI registry + echo "Pulling skeleton chart: oci://${OCI_REGISTRY}/release-orchestrator --version ${SKELETON_VERSION}" + helm pull "oci://${OCI_REGISTRY}/release-orchestrator" --version "${SKELETON_VERSION}" --untar + + cd release-orchestrator + + # Hydrate Chart.yaml + yq -i ".version = \"${BUNDLE_VERSION}\"" Chart.yaml + yq -i ".appVersion = \"${BUNDLE_VERSION}\"" Chart.yaml + + # Hydrate values.yaml yq -i ".global.targetNamespace = \"v${XY}-openshift-virtualization-tenant\"" values.yaml + yq -i ".global.releasePlan = \"v${XY}-component-releaseplan\"" values.yaml + yq -i ".global.bundleReleasePlan = \"v${XY}-bundle-releaseplan\"" values.yaml # Update values.yaml with snapshots from SNAPSHOTS_TO_RELEASE echo "$SNAPSHOTS_TO_RELEASE" | jq -r '{snapshots: .}' | yq eval -P '.' > /tmp/snapshots_with_key.yaml yq eval-all '. as $item ireduce ({}; . * $item)' values.yaml /tmp/snapshots_with_key.yaml -i - DOCKER_CONFIG=$(cat /tmp/quay-builds-creds/.dockerconfigjson) - QUAY_USERNAME=$(echo "${DOCKER_CONFIG}" | jq -r '.auths | to_entries[] | select(.key | contains("quay.io")) | .value.username') - QUAY_PASSWORD=$(echo "${DOCKER_CONFIG}" | jq -r '.auths | to_entries[] | select(.key | contains("quay.io")) | .value.password') - QUAY_URL=$(echo "${DOCKER_CONFIG}" | jq -r '.auths | to_entries[] | .key') + # Validate chart before pushing + echo "Validating chart with helm lint..." + if ! helm lint .; then + echo "ERROR: Chart validation failed" + exit 1 + fi - echo "${QUAY_PASSWORD}" | helm registry login quay.io --username "${QUAY_USERNAME}" --password-stdin + # Package and push + helm package . + PACKAGE_FILE=$(ls release-orchestrator-*.tgz 2>/dev/null | head -1) + + if [[ -z "${PACKAGE_FILE}" || ! -f "${PACKAGE_FILE}" ]]; then + echo "ERROR: Failed to find packaged chart file" + exit 1 + fi - PACKAGE_OUTPUT=$(helm package . 2>&1) - PACKAGE_FILE=$(echo "${PACKAGE_OUTPUT}" | grep -oP 'Successfully packaged chart and saved it to: \K.*') + echo "Pushing chart to oci://${OCI_REGISTRY}" + helm push "${PACKAGE_FILE}" "oci://${OCI_REGISTRY}" - helm push $PACKAGE_FILE oci://${QUAY_URL} + echo "Published release-orchestrator:${BUNDLE_VERSION} to oci://${OCI_REGISTRY}" From 193bc3e45e57077bdf9fdbcefdf5f6859540107d Mon Sep 17 00:00:00 2001 From: thason Date: Wed, 21 Jan 2026 08:51:35 +0200 Subject: [PATCH 59/88] Enhance update-bundle pipeline with detailed logging and validation steps, including snapshot data fetching, commit consistency checks, and improved error handling. Update Chart.yaml and values.yaml hydration processes, ensuring proper versioning and snapshot injection. Streamline git operations and OCI registry interactions for better clarity and reliability. --- pipelines/update-bundle.yaml | 86 ++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 29 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 9cbc7a4..89ffe0d 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -41,29 +41,39 @@ spec: name: hco-updater-gitlab-token script: | #!/usr/bin/env bash - set -eo pipefail + set -eox pipefail + echo "=== PHASE 1: Fetching snapshot data ===" SNAPSHOT_ID=$(echo "$(params.SNAPSHOT)" | awk -F'/' '{print $2}') SNAPSHOT_DATA=$(kubectl get snapshot $SNAPSHOT_ID -ojson) NAMESPACE=$(jq -r '.metadata.namespace' <<< "$SNAPSHOT_DATA") APPLICATION=$(jq -r '.spec.application' <<< "$SNAPSHOT_DATA") VERSION=$(echo "$NAMESPACE" | cut -d'-' -f1,2) + echo "Snapshot ID: $SNAPSHOT_ID" + echo "Namespace: $NAMESPACE" + echo "Application: $APPLICATION" + echo "Version: $VERSION" + + echo "=== PHASE 2: Cloning hco-bundle-registry ===" REPO_URL="https://gitlab.cee.redhat.com/openshift-virtualization/konflux-builds/${VERSION}/hco-bundle-registry.git" REPO_URL=$(echo "$REPO_URL" | sed "s|https://|https://oauth2:${GITLAB_TOKEN}@|") - git clone $REPO_URL --depth 50 cd hco-bundle-registry git remote set-url origin "$REPO_URL" git config user.name "submodule-sync" git config user.email "no-reply@redhat.com" + echo "=== PHASE 3: Validating commit consistency ===" IMAGES=$(jq -r '.spec.components[].containerImage' <<< "$SNAPSHOT_DATA") - - # Make sure all the commits in every component are the same if jq -e '[.spec.components[].source.git.revision] | unique | length == 1' <<< "$SNAPSHOT_DATA" > /dev/null; then - echo "The snapshot has all the components pointing to the same commit, continuing." + echo "OK: All components point to the same commit" else - echo "Commits are inconsistent!" + echo "ERROR: Commits are inconsistent!" + echo "Component revisions:" + jq -r '.spec.components[] | "\(.name): \(.source.git.revision)"' <<< "$SNAPSHOT_DATA" + echo "" + echo "Unique revisions found:" + jq -r '[.spec.components[].source.git.revision] | unique | .[]' <<< "$SNAPSHOT_DATA" exit 1 fi @@ -91,36 +101,43 @@ spec: && mv "$snapshots_file.tmp" "$snapshots_file" } + echo "=== PHASE 4: Updating image references ===" update_images_snapshots + echo "=== PHASE 5: Committing and pushing changes ===" git add . - # Check if there are actually changes before committing if ! git diff-index --quiet HEAD; then git commit -m "Update HCO bundle registry with new images" git pull --rebase origin main git push origin main + echo "OK: Changes pushed to GitLab" else - echo "No changes detected in the bundle registry. Skipping git push." + echo "SKIP: No changes detected in the bundle registry" fi if [[ "$(params.SNAPSHOT)" == *"hco-bundle-registry"* ]]; then - # Use [0] to get single value (all components have same revision, validated above) + echo "=== PHASE 6: Preparing release data for hco-bundle-registry ===" REPO_REVISION=$(jq -r '.spec.components[0].source.git.revision' <<< "$SNAPSHOT_DATA") + echo "Repo revision: $REPO_REVISION" BUNDLE_VERSION=$(cat build-bundle.json | jq -r '.metadata.Version | "\(.XY).\(.Z)-\(.os).\(.release)" | sub("^v"; "")') + echo "Bundle version: $BUNDLE_VERSION" echo -n "$BUNDLE_VERSION" > /tekton/results/bundle-version - # Make sure we are getting the exact snapshots from the bundle git checkout $REPO_REVISION - - # Update the bundle snapshot as its not updated in this commit update_images_snapshots SNAPSHOTS_TO_RELEASE=$(cat $snapshots_file) echo -n "$SNAPSHOTS_TO_RELEASE" > /tekton/results/snapshots-to-release + echo "OK: Release data written to results" fi + + echo "=== update-bundle step completed ===" - name: push-release-chart image: quay.io/redhat-user-workloads/ocp-virt-images-tenant/pipeline-tools@sha256:18f9f819e9393891ce7ae19414a5672786e3efb120bdeaa2c254d8ba5d8e2493 + env: + - name: HOME + value: /tmp envFrom: - secretRef: name: hco-updater-gitlab-token @@ -132,28 +149,32 @@ spec: readOnly: true script: | #!/usr/bin/env bash - set -eo pipefail + set -eox pipefail - # Only continue if its releasing hco-bundle-registry + echo "=== PHASE 1: Checking if hco-bundle-registry release ===" if [[ "$(params.SNAPSHOT)" != *"hco-bundle-registry"* ]]; then - echo "Skipping push-release-chart: snapshot parameter does not contain 'hco-bundle-registry'" + echo "SKIP: Snapshot does not contain 'hco-bundle-registry'" exit 0 fi + echo "OK: This is an hco-bundle-registry release" - # Configuration + echo "=== PHASE 2: Loading configuration ===" OCI_REGISTRY="quay.io/openshift-virtualization/release-chart" SKELETON_VERSION="$(params.SKELETON_CHART_VERSION)" + echo "OCI Registry: $OCI_REGISTRY" + echo "Skeleton Version: $SKELETON_VERSION" - # Read results from previous step + echo "=== PHASE 3: Reading results from previous step ===" SNAPSHOTS_TO_RELEASE=$(cat /tekton/results/snapshots-to-release) BUNDLE_VERSION=$(cat /tekton/results/bundle-version) XY=$(echo "$BUNDLE_VERSION" | cut -d'.' -f1,2 | tr '.' '-') + echo "Bundle Version: $BUNDLE_VERSION" + echo "XY Version: $XY" TMPDIR=$(mktemp -d) cd "$TMPDIR" - export HOME=/tmp - # Registry login - extract first matching quay.io credentials + echo "=== PHASE 4: Registry login ===" DOCKER_CONFIG=$(cat /tmp/quay-builds-creds/.dockerconfigjson) QUAY_USERNAME=$(echo "${DOCKER_CONFIG}" | jq -r '[.auths | to_entries[] | select(.key | contains("quay.io"))] | first | .value.username') QUAY_PASSWORD=$(echo "${DOCKER_CONFIG}" | jq -r '[.auths | to_entries[] | select(.key | contains("quay.io"))] | first | .value.password') @@ -162,36 +183,41 @@ spec: echo "ERROR: Could not extract quay.io credentials from secret" exit 1 fi + echo "OK: Extracted credentials for user: $QUAY_USERNAME" echo "${QUAY_PASSWORD}" | helm registry login quay.io --username "${QUAY_USERNAME}" --password-stdin + echo "OK: Logged in to quay.io" - # Pull skeleton chart from OCI registry - echo "Pulling skeleton chart: oci://${OCI_REGISTRY}/release-orchestrator --version ${SKELETON_VERSION}" + echo "=== PHASE 5: Pulling skeleton chart ===" + echo "Pulling: oci://${OCI_REGISTRY}/release-orchestrator --version ${SKELETON_VERSION}" helm pull "oci://${OCI_REGISTRY}/release-orchestrator" --version "${SKELETON_VERSION}" --untar - cd release-orchestrator + echo "OK: Skeleton chart extracted" - # Hydrate Chart.yaml + echo "=== PHASE 6: Hydrating Chart.yaml ===" yq -i ".version = \"${BUNDLE_VERSION}\"" Chart.yaml yq -i ".appVersion = \"${BUNDLE_VERSION}\"" Chart.yaml + echo "OK: Chart.yaml updated with version $BUNDLE_VERSION" - # Hydrate values.yaml + echo "=== PHASE 7: Hydrating values.yaml ===" yq -i ".global.targetNamespace = \"v${XY}-openshift-virtualization-tenant\"" values.yaml yq -i ".global.releasePlan = \"v${XY}-component-releaseplan\"" values.yaml yq -i ".global.bundleReleasePlan = \"v${XY}-bundle-releaseplan\"" values.yaml + echo "OK: Global values set" - # Update values.yaml with snapshots from SNAPSHOTS_TO_RELEASE + echo "=== PHASE 8: Injecting snapshots ===" echo "$SNAPSHOTS_TO_RELEASE" | jq -r '{snapshots: .}' | yq eval -P '.' > /tmp/snapshots_with_key.yaml yq eval-all '. as $item ireduce ({}; . * $item)' values.yaml /tmp/snapshots_with_key.yaml -i + echo "OK: Snapshots injected into values.yaml" - # Validate chart before pushing - echo "Validating chart with helm lint..." + echo "=== PHASE 9: Validating chart ===" if ! helm lint .; then echo "ERROR: Chart validation failed" exit 1 fi + echo "OK: Chart passed validation" - # Package and push + echo "=== PHASE 10: Packaging chart ===" helm package . PACKAGE_FILE=$(ls release-orchestrator-*.tgz 2>/dev/null | head -1) @@ -199,8 +225,10 @@ spec: echo "ERROR: Failed to find packaged chart file" exit 1 fi + echo "OK: Packaged as $PACKAGE_FILE" - echo "Pushing chart to oci://${OCI_REGISTRY}" + echo "=== PHASE 11: Pushing to OCI registry ===" helm push "${PACKAGE_FILE}" "oci://${OCI_REGISTRY}" + echo "=== push-release-chart step completed ===" echo "Published release-orchestrator:${BUNDLE_VERSION} to oci://${OCI_REGISTRY}" From cd431777ffcf1dd7f276663f2b75d8c038ac09a7 Mon Sep 17 00:00:00 2001 From: thason Date: Wed, 21 Jan 2026 17:53:56 +0200 Subject: [PATCH 60/88] Refactor update-bundle pipeline to improve script clarity and organization. Adjust phase logging, update variable names for better context, and ensure correct handling of chart packaging and registry interactions. Enhance versioning in Chart.yaml and streamline OCI registry push process. --- pipelines/update-bundle.yaml | 44 +++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 89ffe0d..544b6f7 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -41,7 +41,7 @@ spec: name: hco-updater-gitlab-token script: | #!/usr/bin/env bash - set -eox pipefail + set -eo pipefail echo "=== PHASE 1: Fetching snapshot data ===" SNAPSHOT_ID=$(echo "$(params.SNAPSHOT)" | awk -F'/' '{print $2}') @@ -149,7 +149,7 @@ spec: readOnly: true script: | #!/usr/bin/env bash - set -eox pipefail + set -eo pipefail echo "=== PHASE 1: Checking if hco-bundle-registry release ===" if [[ "$(params.SNAPSHOT)" != *"hco-bundle-registry"* ]]; then @@ -158,19 +158,23 @@ spec: fi echo "OK: This is an hco-bundle-registry release" - echo "=== PHASE 2: Loading configuration ===" - OCI_REGISTRY="quay.io/openshift-virtualization/release-chart" - SKELETON_VERSION="$(params.SKELETON_CHART_VERSION)" - echo "OCI Registry: $OCI_REGISTRY" - echo "Skeleton Version: $SKELETON_VERSION" - - echo "=== PHASE 3: Reading results from previous step ===" + echo "=== PHASE 2: Reading results from previous step ===" SNAPSHOTS_TO_RELEASE=$(cat /tekton/results/snapshots-to-release) BUNDLE_VERSION=$(cat /tekton/results/bundle-version) XY=$(echo "$BUNDLE_VERSION" | cut -d'.' -f1,2 | tr '.' '-') echo "Bundle Version: $BUNDLE_VERSION" echo "XY Version: $XY" + echo "=== PHASE 3: Loading configuration ===" + CHART_NAME="hco-bundle-registry-rhel9" + SKELETON_REGISTRY="quay.io/openshift-virtualization/release-chart" + TARGET_REGISTRY="quay.io/openshift-virtualization/konflux-builds/v${XY}" + SKELETON_VERSION="$(params.SKELETON_CHART_VERSION)" + echo "Chart Name: $CHART_NAME" + echo "Skeleton Registry: $SKELETON_REGISTRY" + echo "Target Registry: $TARGET_REGISTRY" + echo "Skeleton Version: $SKELETON_VERSION" + TMPDIR=$(mktemp -d) cd "$TMPDIR" @@ -189,15 +193,19 @@ spec: echo "OK: Logged in to quay.io" echo "=== PHASE 5: Pulling skeleton chart ===" - echo "Pulling: oci://${OCI_REGISTRY}/release-orchestrator --version ${SKELETON_VERSION}" - helm pull "oci://${OCI_REGISTRY}/release-orchestrator" --version "${SKELETON_VERSION}" --untar - cd release-orchestrator + echo "Pulling: oci://${SKELETON_REGISTRY}/${CHART_NAME} --version ${SKELETON_VERSION}" + helm pull "oci://${SKELETON_REGISTRY}/${CHART_NAME}" --version "${SKELETON_VERSION}" --untar + cd "${CHART_NAME}" echo "OK: Skeleton chart extracted" echo "=== PHASE 6: Hydrating Chart.yaml ===" - yq -i ".version = \"${BUNDLE_VERSION}\"" Chart.yaml - yq -i ".appVersion = \"${BUNDLE_VERSION}\"" Chart.yaml - echo "OK: Chart.yaml updated with version $BUNDLE_VERSION" + CHART_VERSION="releases-${BUNDLE_VERSION}" + APP_VERSION="v${BUNDLE_VERSION}" + yq -i ".version = \"${CHART_VERSION}\"" Chart.yaml + yq -i ".appVersion = \"${APP_VERSION}\"" Chart.yaml + echo "OK: Chart.yaml updated" + echo " version (OCI tag): $CHART_VERSION" + echo " appVersion: $APP_VERSION" echo "=== PHASE 7: Hydrating values.yaml ===" yq -i ".global.targetNamespace = \"v${XY}-openshift-virtualization-tenant\"" values.yaml @@ -219,7 +227,7 @@ spec: echo "=== PHASE 10: Packaging chart ===" helm package . - PACKAGE_FILE=$(ls release-orchestrator-*.tgz 2>/dev/null | head -1) + PACKAGE_FILE=$(ls ${CHART_NAME}-*.tgz 2>/dev/null | head -1) if [[ -z "${PACKAGE_FILE}" || ! -f "${PACKAGE_FILE}" ]]; then echo "ERROR: Failed to find packaged chart file" @@ -228,7 +236,7 @@ spec: echo "OK: Packaged as $PACKAGE_FILE" echo "=== PHASE 11: Pushing to OCI registry ===" - helm push "${PACKAGE_FILE}" "oci://${OCI_REGISTRY}" + helm push "${PACKAGE_FILE}" "oci://${TARGET_REGISTRY}" echo "=== push-release-chart step completed ===" - echo "Published release-orchestrator:${BUNDLE_VERSION} to oci://${OCI_REGISTRY}" + echo "Published ${CHART_NAME}:${CHART_VERSION} to oci://${TARGET_REGISTRY}" From 5b5ed1a709600860f90af5bae5f5311924869289 Mon Sep 17 00:00:00 2001 From: thason Date: Thu, 22 Jan 2026 10:04:45 +0200 Subject: [PATCH 61/88] Update chart versioning logic in update-bundle pipeline for improved clarity. Transform BUNDLE_VERSION format to enhance readability in Chart.yaml, ensuring consistent versioning with clearer semantics. --- pipelines/update-bundle.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 544b6f7..262a992 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -199,7 +199,10 @@ spec: echo "OK: Skeleton chart extracted" echo "=== PHASE 6: Hydrating Chart.yaml ===" - CHART_VERSION="releases-${BUNDLE_VERSION}" + # Transform 4.99.0-rhel9.2559 to 4.99.0-releases.2559 for clearer chart versioning + SEMVER=$(echo "$BUNDLE_VERSION" | cut -d'-' -f1) + RELEASE_NUM=$(echo "$BUNDLE_VERSION" | grep -oE '[0-9]+$') + CHART_VERSION="${SEMVER}-releases.${RELEASE_NUM}" APP_VERSION="v${BUNDLE_VERSION}" yq -i ".version = \"${CHART_VERSION}\"" Chart.yaml yq -i ".appVersion = \"${APP_VERSION}\"" Chart.yaml From 6cff38038df47cc12d79e04acb75ceae0cc9d74e Mon Sep 17 00:00:00 2001 From: thason Date: Thu, 5 Feb 2026 09:46:19 +0200 Subject: [PATCH 62/88] Add .gitignore and new MDC files for execution layer and Tekton pipelines - Introduced .gitignore to exclude cursor plans. - Added execution-layer-reference.mdc for resilient execution layer pattern guidelines. - Created tekton-pipelines.mdc outlining best practices for Tekton pipeline development, emphasizing resilient execution patterns and structured logging. --- .cursor/rules/execution-layer-reference.mdc | 149 ++++++ .cursor/rules/tekton-pipelines.mdc | 104 ++++ .gitignore | 1 + pipelines/update-bundle.yaml | 511 ++++++++++++++++++-- 4 files changed, 714 insertions(+), 51 deletions(-) create mode 100644 .cursor/rules/execution-layer-reference.mdc create mode 100644 .cursor/rules/tekton-pipelines.mdc create mode 100644 .gitignore diff --git a/.cursor/rules/execution-layer-reference.mdc b/.cursor/rules/execution-layer-reference.mdc new file mode 100644 index 0000000..ebc9f1e --- /dev/null +++ b/.cursor/rules/execution-layer-reference.mdc @@ -0,0 +1,149 @@ +--- +description: Reference implementation for the resilient execution layer pattern +globs: "**/*.yaml" +alwaysApply: false +--- + +# Execution Layer Reference Implementation + +## Full Template + +Copy this template when creating new pipeline steps: + +```bash +#!/usr/bin/env bash + +# ============================================================ +# EXECUTION LAYER - Resilient wrapper for observability +# ============================================================ +SCRIPT_START=$(date +%s) +declare -a ACTION_LOG=() +FINAL_EXIT_CODE=0 + +# Enable debug mode if requested +if [[ "$(params.DEBUG)" == "true" ]]; then + set -x +fi + +exec_action() { + local action_name="$1" + local timeout_secs="${2:-60}" + shift 2 + local cmd="$*" + + local start_ts=$(date +%s) + echo "" + echo "┌─────────────────────────────────────────────────────────────" + echo "│ ACTION: $action_name" + echo "│ CMD: $cmd" + echo "│ TIMEOUT: ${timeout_secs}s" + echo "├─────────────────────────────────────────────────────────────" + + local output exit_code + output=$(timeout "$timeout_secs" bash -c "$cmd" 2>&1) + exit_code=$? + + local end_ts=$(date +%s) + local duration=$((end_ts - start_ts)) + + if [[ -n "$output" ]]; then + echo "$output" | sed 's/^/│ /' + fi + + local status + if [[ $exit_code -eq 0 ]]; then + status="OK" + elif [[ $exit_code -eq 124 ]]; then + status="TIMEOUT" + else + status="FAILED" + fi + + echo "├─────────────────────────────────────────────────────────────" + echo "│ STATUS: $status (exit: $exit_code, duration: ${duration}s)" + echo "└─────────────────────────────────────────────────────────────" + + ACTION_LOG+=("$status|$action_name|exit=$exit_code|${duration}s") + return $exit_code +} + +execution_summary() { + local script_exit_code=$? + local script_end=$(date +%s) + local total_duration=$((script_end - SCRIPT_START)) + + echo "" + echo "╔═════════════════════════════════════════════════════════════" + echo "║ EXECUTION SUMMARY - " + echo "║ Total Duration: ${total_duration}s" + echo "║ Final Exit Code: ${FINAL_EXIT_CODE:-$script_exit_code}" + echo "╠═════════════════════════════════════════════════════════════" + + local ok_count=0 fail_count=0 timeout_count=0 + + for entry in "${ACTION_LOG[@]}"; do + local status=$(echo "$entry" | cut -d'|' -f1) + local action=$(echo "$entry" | cut -d'|' -f2) + local details=$(echo "$entry" | cut -d'|' -f3-) + + case "$status" in + OK) ((ok_count++)); echo "║ ✓ $action ($details)" ;; + FAILED) ((fail_count++)); echo "║ ✗ $action ($details)" ;; + TIMEOUT) ((timeout_count++)); echo "║ ⏱ $action ($details)" ;; + esac + done + + echo "╠═════════════════════════════════════════════════════════════" + echo "║ OK: $ok_count | FAILED: $fail_count | TIMEOUT: $timeout_count" + echo "╚═════════════════════════════════════════════════════════════" + + exit ${FINAL_EXIT_CODE:-$script_exit_code} +} + +trap execution_summary EXIT + +# ============================================================ +# RUN LOGIC - Business logic with fail-fast behavior +# ============================================================ +set -eo pipefail + +# Your business logic here... +``` + +## Usage Patterns + +### Wrapping Commands + +```bash +# With exec_action (preferred for external calls) +if ! exec_action "Fetch data" 60 "kubectl get pod -ojson"; then + echo "ERROR: Failed to fetch data" + FINAL_EXIT_CODE=1 + exit 1 +fi + +# Quick validation (no external call) +if [[ -z "$REQUIRED_VAR" ]]; then + echo "ERROR: REQUIRED_VAR is empty" + FINAL_EXIT_CODE=1 + exit 1 +fi +ACTION_LOG+=("OK|Validate REQUIRED_VAR|exit=0|0s") +``` + +### Early Exit (Success) + +```bash +if [[ "$CONDITION" == "skip" ]]; then + ACTION_LOG+=("OK|Skip - condition met|exit=0|0s") + FINAL_EXIT_CODE=0 + exit 0 +fi +``` + +## Key Principles + +1. **Always set FINAL_EXIT_CODE before exit** - Ensures trap reports correct status +2. **Log manual validations** - Add to ACTION_LOG for visibility +3. **Timeout all external calls** - Prevent indefinite hangs +4. **Validate before use** - Check files/vars exist before operations diff --git a/.cursor/rules/tekton-pipelines.mdc b/.cursor/rules/tekton-pipelines.mdc new file mode 100644 index 0000000..bb12081 --- /dev/null +++ b/.cursor/rules/tekton-pipelines.mdc @@ -0,0 +1,104 @@ +--- +description: Guidelines for Tekton pipeline development with resilient execution patterns +alwaysApply: true +--- + +# Tekton Tasks Repository Guidelines + +## Repository Overview + +This repository contains Tekton pipelines and tasks for OpenShift Virtualization CI/CD workflows. All pipelines follow the **Resilient Execution Layer** pattern for observability and debugging. + +## Key Patterns + +### Resilient Execution Layer + +Every pipeline step MUST include: + +1. **Execution Layer Header** - Initialize tracking at script start: +```bash +SCRIPT_START=$(date +%s) +declare -a ACTION_LOG=() +FINAL_EXIT_CODE=0 +``` + +2. **exec_action() wrapper** - Wrap external commands with timeouts and structured logging: +```bash +exec_action "Action name" "" +``` + +3. **execution_summary() trap** - Guarantee summary output on ANY exit: +```bash +trap execution_summary EXIT +``` + +4. **Fail-fast run logic** - Keep `set -eo pipefail` for business logic after the execution layer. + +### Timeout Guidelines + +| Command Type | Recommended Timeout | +|-------------|---------------------| +| kubectl/oc API calls | 60s | +| git clone | 120s | +| git pull/push | 60s | +| helm pull | 120s | +| helm push | 120s | +| helm lint/package | 30s | +| Registry login | 30s | +| Validation checks | 30s | + +### Validation Requirements + +Before executing any command, validate: +- Required parameters are not empty +- Environment variables (tokens, credentials) exist +- Files exist before reading them +- JSON/YAML is valid before parsing + +### Output Formatting + +Use box-drawing characters for structured output: +- `┌─────` Action start +- `│` Output prefix +- `├─────` Status separator +- `└─────` Action end +- `╔═════` Summary header +- `║` Summary lines +- `╚═════` Summary footer + +## File Structure + +``` +tekton-tasks/ +├── pipelines/ # Full pipeline definitions +│ └── *.yaml +├── fbc/ # FBC-specific tasks +│ └── *.yaml +└── README.md +``` + +## Pipeline Parameters + +Always include a `debug` parameter for verbose output: +```yaml +- name: debug + type: string + default: "false" + description: Enable debug mode with verbose output (set -x) +``` + +## Testing Changes + +Before committing: +1. Validate YAML syntax: `python3 -c "import yaml; yaml.safe_load(open('file.yaml'))"` +2. Validate bash syntax: Extract script and run `bash -n script.sh` +3. Test in a non-production namespace first + +## Commit Messages + +Format: `(): ` + +Examples: +- `feat(pipeline): add new release automation step` +- `fix(update-bundle): handle empty snapshot gracefully` +- `refactor(pipeline): improve error handling and observability` diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..395229e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.cursor/plans/* \ No newline at end of file diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 262a992..39f70e8 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -11,6 +11,10 @@ spec: - name: skeleton-chart-version type: string default: "0.0.0-skeleton" + - name: debug + type: string + default: "false" + description: Enable debug mode with verbose output (set -x) tasks: - name: update-bundle params: @@ -18,12 +22,16 @@ spec: value: "$(params.snapshot)" - name: SKELETON_CHART_VERSION value: "$(params.skeleton-chart-version)" + - name: DEBUG + value: "$(params.debug)" taskSpec: params: - name: SNAPSHOT type: string - name: SKELETON_CHART_VERSION type: string + - name: DEBUG + type: string results: - name: snapshots-to-release description: Contents of the snapshots.json file @@ -41,41 +49,182 @@ spec: name: hco-updater-gitlab-token script: | #!/usr/bin/env bash + + # ============================================================ + # EXECUTION LAYER - Resilient wrapper for observability + # ============================================================ + SCRIPT_START=$(date +%s) + declare -a ACTION_LOG=() + FINAL_EXIT_CODE=0 + + # Enable debug mode if requested + if [[ "$(params.DEBUG)" == "true" ]]; then + set -x + fi + + exec_action() { + local action_name="$1" + local timeout_secs="${2:-60}" + shift 2 + local cmd="$*" + + local start_ts=$(date +%s) + echo "" + echo "┌─────────────────────────────────────────────────────────────" + echo "│ ACTION: $action_name" + echo "│ CMD: $cmd" + echo "│ TIMEOUT: ${timeout_secs}s" + echo "├─────────────────────────────────────────────────────────────" + + local output + local exit_code + output=$(timeout "$timeout_secs" bash -c "$cmd" 2>&1) + exit_code=$? + + local end_ts=$(date +%s) + local duration=$((end_ts - start_ts)) + + if [[ -n "$output" ]]; then + echo "$output" | sed 's/^/│ /' + fi + + local status + if [[ $exit_code -eq 0 ]]; then + status="OK" + elif [[ $exit_code -eq 124 ]]; then + status="TIMEOUT" + else + status="FAILED" + fi + + echo "├─────────────────────────────────────────────────────────────" + echo "│ STATUS: $status (exit: $exit_code, duration: ${duration}s)" + echo "└─────────────────────────────────────────────────────────────" + + ACTION_LOG+=("$status|$action_name|exit=$exit_code|${duration}s") + return $exit_code + } + + execution_summary() { + local script_exit_code=$? + local script_end=$(date +%s) + local total_duration=$((script_end - SCRIPT_START)) + + echo "" + echo "╔═════════════════════════════════════════════════════════════" + echo "║ EXECUTION SUMMARY - update-bundle" + echo "║ Total Duration: ${total_duration}s" + echo "║ Final Exit Code: ${FINAL_EXIT_CODE:-$script_exit_code}" + echo "╠═════════════════════════════════════════════════════════════" + + local ok_count=0 fail_count=0 timeout_count=0 + + for entry in "${ACTION_LOG[@]}"; do + local status=$(echo "$entry" | cut -d'|' -f1) + local action=$(echo "$entry" | cut -d'|' -f2) + local details=$(echo "$entry" | cut -d'|' -f3-) + + case "$status" in + OK) ((ok_count++)); echo "║ ✓ $action ($details)" ;; + FAILED) ((fail_count++)); echo "║ ✗ $action ($details)" ;; + TIMEOUT) ((timeout_count++)); echo "║ ⏱ $action ($details)" ;; + esac + done + + echo "╠═════════════════════════════════════════════════════════════" + echo "║ OK: $ok_count | FAILED: $fail_count | TIMEOUT: $timeout_count" + echo "╚═════════════════════════════════════════════════════════════" + + exit ${FINAL_EXIT_CODE:-$script_exit_code} + } + + trap execution_summary EXIT + + # ============================================================ + # RUN LOGIC - Business logic with fail-fast behavior + # ============================================================ set -eo pipefail echo "=== PHASE 1: Fetching snapshot data ===" + + # Validate SNAPSHOT parameter + if [[ -z "$(params.SNAPSHOT)" ]]; then + echo "ERROR: SNAPSHOT parameter is empty" + FINAL_EXIT_CODE=1 + exit 1 + fi + ACTION_LOG+=("OK|Validate SNAPSHOT parameter|exit=0|0s") + SNAPSHOT_ID=$(echo "$(params.SNAPSHOT)" | awk -F'/' '{print $2}') + if [[ -z "$SNAPSHOT_ID" ]]; then + echo "ERROR: Could not extract SNAPSHOT_ID from: $(params.SNAPSHOT)" + FINAL_EXIT_CODE=1 + exit 1 + fi + ACTION_LOG+=("OK|Extract SNAPSHOT_ID|exit=0|0s") + echo "│ Snapshot ID: $SNAPSHOT_ID" + + if ! exec_action "Fetch snapshot from Kubernetes" 60 "kubectl get snapshot $SNAPSHOT_ID -ojson"; then + echo "ERROR: Failed to fetch snapshot $SNAPSHOT_ID" + FINAL_EXIT_CODE=1 + exit 1 + fi SNAPSHOT_DATA=$(kubectl get snapshot $SNAPSHOT_ID -ojson) + + # Validate JSON response + if ! echo "$SNAPSHOT_DATA" | jq -e . > /dev/null 2>&1; then + echo "ERROR: Invalid JSON response from kubectl" + FINAL_EXIT_CODE=1 + exit 1 + fi + ACTION_LOG+=("OK|Validate snapshot JSON|exit=0|0s") + NAMESPACE=$(jq -r '.metadata.namespace' <<< "$SNAPSHOT_DATA") APPLICATION=$(jq -r '.spec.application' <<< "$SNAPSHOT_DATA") VERSION=$(echo "$NAMESPACE" | cut -d'-' -f1,2) - echo "Snapshot ID: $SNAPSHOT_ID" - echo "Namespace: $NAMESPACE" - echo "Application: $APPLICATION" - echo "Version: $VERSION" + echo "│ Namespace: $NAMESPACE" + echo "│ Application: $APPLICATION" + echo "│ Version: $VERSION" echo "=== PHASE 2: Cloning hco-bundle-registry ===" + + # Validate GITLAB_TOKEN + if [[ -z "${GITLAB_TOKEN:-}" ]]; then + echo "ERROR: GITLAB_TOKEN environment variable is not set" + FINAL_EXIT_CODE=1 + exit 1 + fi + ACTION_LOG+=("OK|Validate GITLAB_TOKEN|exit=0|0s") + REPO_URL="https://gitlab.cee.redhat.com/openshift-virtualization/konflux-builds/${VERSION}/hco-bundle-registry.git" - REPO_URL=$(echo "$REPO_URL" | sed "s|https://|https://oauth2:${GITLAB_TOKEN}@|") - git clone $REPO_URL --depth 50 + REPO_URL_WITH_AUTH=$(echo "$REPO_URL" | sed "s|https://|https://oauth2:${GITLAB_TOKEN}@|") + + if ! exec_action "Clone hco-bundle-registry" 120 "git clone $REPO_URL_WITH_AUTH --depth 50 hco-bundle-registry"; then + echo "ERROR: Failed to clone repository" + FINAL_EXIT_CODE=1 + exit 1 + fi + cd hco-bundle-registry - git remote set-url origin "$REPO_URL" + git remote set-url origin "$REPO_URL_WITH_AUTH" git config user.name "submodule-sync" git config user.email "no-reply@redhat.com" + ACTION_LOG+=("OK|Configure git identity|exit=0|0s") echo "=== PHASE 3: Validating commit consistency ===" IMAGES=$(jq -r '.spec.components[].containerImage' <<< "$SNAPSHOT_DATA") - if jq -e '[.spec.components[].source.git.revision] | unique | length == 1' <<< "$SNAPSHOT_DATA" > /dev/null; then - echo "OK: All components point to the same commit" - else + + if ! exec_action "Validate commit consistency" 30 "jq -e '[.spec.components[].source.git.revision] | unique | length == 1' <<< '$SNAPSHOT_DATA' > /dev/null"; then echo "ERROR: Commits are inconsistent!" echo "Component revisions:" jq -r '.spec.components[] | "\(.name): \(.source.git.revision)"' <<< "$SNAPSHOT_DATA" echo "" echo "Unique revisions found:" jq -r '[.spec.components[].source.git.revision] | unique | .[]' <<< "$SNAPSHOT_DATA" + FINAL_EXIT_CODE=1 exit 1 fi + echo "│ OK: All components point to the same commit" function update_images_snapshots() { for img in $IMAGES; do @@ -102,37 +251,85 @@ spec: } echo "=== PHASE 4: Updating image references ===" - update_images_snapshots + if ! exec_action "Update image references" 60 "update_images_snapshots"; then + echo "ERROR: Failed to update image references" + FINAL_EXIT_CODE=1 + exit 1 + fi echo "=== PHASE 5: Committing and pushing changes ===" git add . if ! git diff-index --quiet HEAD; then git commit -m "Update HCO bundle registry with new images" - git pull --rebase origin main - git push origin main - echo "OK: Changes pushed to GitLab" + ACTION_LOG+=("OK|Commit changes|exit=0|0s") + + if ! exec_action "Pull with rebase" 60 "git pull --rebase origin main"; then + echo "ERROR: Failed to pull with rebase" + FINAL_EXIT_CODE=1 + exit 1 + fi + + if ! exec_action "Push to origin" 60 "git push origin main"; then + echo "ERROR: Failed to push to origin" + FINAL_EXIT_CODE=1 + exit 1 + fi + echo "│ OK: Changes pushed to GitLab" else - echo "SKIP: No changes detected in the bundle registry" + ACTION_LOG+=("OK|Skip - No changes detected|exit=0|0s") + echo "│ SKIP: No changes detected in the bundle registry" fi if [[ "$(params.SNAPSHOT)" == *"hco-bundle-registry"* ]]; then echo "=== PHASE 6: Preparing release data for hco-bundle-registry ===" REPO_REVISION=$(jq -r '.spec.components[0].source.git.revision' <<< "$SNAPSHOT_DATA") - echo "Repo revision: $REPO_REVISION" + echo "│ Repo revision: $REPO_REVISION" + if [[ ! -f "build-bundle.json" ]]; then + echo "ERROR: build-bundle.json not found" + FINAL_EXIT_CODE=1 + exit 1 + fi + BUNDLE_VERSION=$(cat build-bundle.json | jq -r '.metadata.Version | "\(.XY).\(.Z)-\(.os).\(.release)" | sub("^v"; "")') - echo "Bundle version: $BUNDLE_VERSION" + if [[ -z "$BUNDLE_VERSION" || "$BUNDLE_VERSION" == "null" ]]; then + echo "ERROR: Failed to extract bundle version" + FINAL_EXIT_CODE=1 + exit 1 + fi + echo "│ Bundle version: $BUNDLE_VERSION" + ACTION_LOG+=("OK|Extract bundle version|exit=0|0s") + echo -n "$BUNDLE_VERSION" > /tekton/results/bundle-version + if [[ ! -f "/tekton/results/bundle-version" ]]; then + echo "ERROR: Failed to write bundle-version result" + FINAL_EXIT_CODE=1 + exit 1 + fi + ACTION_LOG+=("OK|Write bundle-version result|exit=0|0s") - git checkout $REPO_REVISION + if ! exec_action "Checkout release revision" 30 "git checkout $REPO_REVISION"; then + echo "ERROR: Failed to checkout revision $REPO_REVISION" + FINAL_EXIT_CODE=1 + exit 1 + fi + update_images_snapshots + ACTION_LOG+=("OK|Update images for release|exit=0|0s") SNAPSHOTS_TO_RELEASE=$(cat $snapshots_file) echo -n "$SNAPSHOTS_TO_RELEASE" > /tekton/results/snapshots-to-release - echo "OK: Release data written to results" + if [[ ! -f "/tekton/results/snapshots-to-release" ]]; then + echo "ERROR: Failed to write snapshots-to-release result" + FINAL_EXIT_CODE=1 + exit 1 + fi + ACTION_LOG+=("OK|Write snapshots-to-release result|exit=0|0s") + echo "│ OK: Release data written to results" fi echo "=== update-bundle step completed ===" + FINAL_EXIT_CODE=0 - name: push-release-chart image: quay.io/redhat-user-workloads/ocp-virt-images-tenant/pipeline-tools@sha256:18f9f819e9393891ce7ae19414a5672786e3efb120bdeaa2c254d8ba5d8e2493 env: @@ -149,97 +346,309 @@ spec: readOnly: true script: | #!/usr/bin/env bash + + # ============================================================ + # EXECUTION LAYER - Resilient wrapper for observability + # ============================================================ + SCRIPT_START=$(date +%s) + declare -a ACTION_LOG=() + FINAL_EXIT_CODE=0 + + # Enable debug mode if requested + if [[ "$(params.DEBUG)" == "true" ]]; then + set -x + fi + + exec_action() { + local action_name="$1" + local timeout_secs="${2:-60}" + shift 2 + local cmd="$*" + + local start_ts=$(date +%s) + echo "" + echo "┌─────────────────────────────────────────────────────────────" + echo "│ ACTION: $action_name" + echo "│ CMD: $cmd" + echo "│ TIMEOUT: ${timeout_secs}s" + echo "├─────────────────────────────────────────────────────────────" + + local output + local exit_code + output=$(timeout "$timeout_secs" bash -c "$cmd" 2>&1) + exit_code=$? + + local end_ts=$(date +%s) + local duration=$((end_ts - start_ts)) + + if [[ -n "$output" ]]; then + echo "$output" | sed 's/^/│ /' + fi + + local status + if [[ $exit_code -eq 0 ]]; then + status="OK" + elif [[ $exit_code -eq 124 ]]; then + status="TIMEOUT" + else + status="FAILED" + fi + + echo "├─────────────────────────────────────────────────────────────" + echo "│ STATUS: $status (exit: $exit_code, duration: ${duration}s)" + echo "└─────────────────────────────────────────────────────────────" + + ACTION_LOG+=("$status|$action_name|exit=$exit_code|${duration}s") + return $exit_code + } + + execution_summary() { + local script_exit_code=$? + local script_end=$(date +%s) + local total_duration=$((script_end - SCRIPT_START)) + + echo "" + echo "╔═════════════════════════════════════════════════════════════" + echo "║ EXECUTION SUMMARY - push-release-chart" + echo "║ Total Duration: ${total_duration}s" + echo "║ Final Exit Code: ${FINAL_EXIT_CODE:-$script_exit_code}" + echo "╠═════════════════════════════════════════════════════════════" + + local ok_count=0 fail_count=0 timeout_count=0 + + for entry in "${ACTION_LOG[@]}"; do + local status=$(echo "$entry" | cut -d'|' -f1) + local action=$(echo "$entry" | cut -d'|' -f2) + local details=$(echo "$entry" | cut -d'|' -f3-) + + case "$status" in + OK) ((ok_count++)); echo "║ ✓ $action ($details)" ;; + FAILED) ((fail_count++)); echo "║ ✗ $action ($details)" ;; + TIMEOUT) ((timeout_count++)); echo "║ ⏱ $action ($details)" ;; + esac + done + + echo "╠═════════════════════════════════════════════════════════════" + echo "║ OK: $ok_count | FAILED: $fail_count | TIMEOUT: $timeout_count" + echo "╚═════════════════════════════════════════════════════════════" + + exit ${FINAL_EXIT_CODE:-$script_exit_code} + } + + trap execution_summary EXIT + + # ============================================================ + # RUN LOGIC - Business logic with fail-fast behavior + # ============================================================ set -eo pipefail echo "=== PHASE 1: Checking if hco-bundle-registry release ===" if [[ "$(params.SNAPSHOT)" != *"hco-bundle-registry"* ]]; then - echo "SKIP: Snapshot does not contain 'hco-bundle-registry'" + ACTION_LOG+=("OK|Skip - Not hco-bundle-registry|exit=0|0s") + echo "│ SKIP: Snapshot does not contain 'hco-bundle-registry'" + FINAL_EXIT_CODE=0 exit 0 fi - echo "OK: This is an hco-bundle-registry release" + ACTION_LOG+=("OK|Validate snapshot type|exit=0|0s") + echo "│ OK: This is an hco-bundle-registry release" echo "=== PHASE 2: Reading results from previous step ===" + + # Validate result files exist + if [[ ! -f "/tekton/results/snapshots-to-release" ]]; then + echo "ERROR: snapshots-to-release result file not found" + FINAL_EXIT_CODE=1 + exit 1 + fi + if [[ ! -f "/tekton/results/bundle-version" ]]; then + echo "ERROR: bundle-version result file not found" + FINAL_EXIT_CODE=1 + exit 1 + fi + ACTION_LOG+=("OK|Validate result files exist|exit=0|0s") + SNAPSHOTS_TO_RELEASE=$(cat /tekton/results/snapshots-to-release) BUNDLE_VERSION=$(cat /tekton/results/bundle-version) + + if [[ -z "$BUNDLE_VERSION" ]]; then + echo "ERROR: bundle-version is empty" + FINAL_EXIT_CODE=1 + exit 1 + fi + ACTION_LOG+=("OK|Read previous step results|exit=0|0s") + XY=$(echo "$BUNDLE_VERSION" | cut -d'.' -f1,2 | tr '.' '-') - echo "Bundle Version: $BUNDLE_VERSION" - echo "XY Version: $XY" + echo "│ Bundle Version: $BUNDLE_VERSION" + echo "│ XY Version: $XY" echo "=== PHASE 3: Loading configuration ===" CHART_NAME="hco-bundle-registry-rhel9" SKELETON_REGISTRY="quay.io/openshift-virtualization/release-chart" TARGET_REGISTRY="quay.io/openshift-virtualization/konflux-builds/v${XY}" SKELETON_VERSION="$(params.SKELETON_CHART_VERSION)" - echo "Chart Name: $CHART_NAME" - echo "Skeleton Registry: $SKELETON_REGISTRY" - echo "Target Registry: $TARGET_REGISTRY" - echo "Skeleton Version: $SKELETON_VERSION" + echo "│ Chart Name: $CHART_NAME" + echo "│ Skeleton Registry: $SKELETON_REGISTRY" + echo "│ Target Registry: $TARGET_REGISTRY" + echo "│ Skeleton Version: $SKELETON_VERSION" + ACTION_LOG+=("OK|Load configuration|exit=0|0s") TMPDIR=$(mktemp -d) cd "$TMPDIR" echo "=== PHASE 4: Registry login ===" + + # Validate credentials file exists + if [[ ! -f "/tmp/quay-builds-creds/.dockerconfigjson" ]]; then + echo "ERROR: Quay credentials file not found at /tmp/quay-builds-creds/.dockerconfigjson" + FINAL_EXIT_CODE=1 + exit 1 + fi + DOCKER_CONFIG=$(cat /tmp/quay-builds-creds/.dockerconfigjson) + + # Validate JSON + if ! echo "$DOCKER_CONFIG" | jq -e . > /dev/null 2>&1; then + echo "ERROR: Invalid JSON in docker config" + FINAL_EXIT_CODE=1 + exit 1 + fi + ACTION_LOG+=("OK|Validate credentials file|exit=0|0s") + QUAY_USERNAME=$(echo "${DOCKER_CONFIG}" | jq -r '[.auths | to_entries[] | select(.key | contains("quay.io"))] | first | .value.username') QUAY_PASSWORD=$(echo "${DOCKER_CONFIG}" | jq -r '[.auths | to_entries[] | select(.key | contains("quay.io"))] | first | .value.password') if [[ -z "${QUAY_USERNAME}" || "${QUAY_USERNAME}" == "null" ]]; then echo "ERROR: Could not extract quay.io credentials from secret" + FINAL_EXIT_CODE=1 exit 1 fi - echo "OK: Extracted credentials for user: $QUAY_USERNAME" + ACTION_LOG+=("OK|Extract Quay credentials|exit=0|0s") + echo "│ OK: Extracted credentials for user: $QUAY_USERNAME" - echo "${QUAY_PASSWORD}" | helm registry login quay.io --username "${QUAY_USERNAME}" --password-stdin - echo "OK: Logged in to quay.io" + if ! exec_action "Login to Quay registry" 30 "echo '***' | helm registry login quay.io --username '${QUAY_USERNAME}' --password-stdin"; then + # Retry with actual password (exec_action masks it) + if ! echo "${QUAY_PASSWORD}" | helm registry login quay.io --username "${QUAY_USERNAME}" --password-stdin; then + echo "ERROR: Failed to login to Quay registry" + FINAL_EXIT_CODE=1 + exit 1 + fi + else + # Actually login with real password + echo "${QUAY_PASSWORD}" | helm registry login quay.io --username "${QUAY_USERNAME}" --password-stdin > /dev/null 2>&1 + fi + echo "│ OK: Logged in to quay.io" echo "=== PHASE 5: Pulling skeleton chart ===" - echo "Pulling: oci://${SKELETON_REGISTRY}/${CHART_NAME} --version ${SKELETON_VERSION}" - helm pull "oci://${SKELETON_REGISTRY}/${CHART_NAME}" --version "${SKELETON_VERSION}" --untar + echo "│ Pulling: oci://${SKELETON_REGISTRY}/${CHART_NAME} --version ${SKELETON_VERSION}" + + if ! exec_action "Pull skeleton chart" 120 "helm pull 'oci://${SKELETON_REGISTRY}/${CHART_NAME}' --version '${SKELETON_VERSION}' --untar"; then + echo "ERROR: Failed to pull skeleton chart" + FINAL_EXIT_CODE=1 + exit 1 + fi + + if [[ ! -d "${CHART_NAME}" ]]; then + echo "ERROR: Chart directory ${CHART_NAME} not found after pull" + FINAL_EXIT_CODE=1 + exit 1 + fi cd "${CHART_NAME}" - echo "OK: Skeleton chart extracted" + echo "│ OK: Skeleton chart extracted" echo "=== PHASE 6: Hydrating Chart.yaml ===" + + if [[ ! -f "Chart.yaml" ]]; then + echo "ERROR: Chart.yaml not found" + FINAL_EXIT_CODE=1 + exit 1 + fi + # Transform 4.99.0-rhel9.2559 to 4.99.0-releases.2559 for clearer chart versioning SEMVER=$(echo "$BUNDLE_VERSION" | cut -d'-' -f1) RELEASE_NUM=$(echo "$BUNDLE_VERSION" | grep -oE '[0-9]+$') + + if [[ -z "$SEMVER" || -z "$RELEASE_NUM" ]]; then + echo "ERROR: Failed to parse bundle version: $BUNDLE_VERSION" + FINAL_EXIT_CODE=1 + exit 1 + fi + CHART_VERSION="${SEMVER}-releases.${RELEASE_NUM}" APP_VERSION="v${BUNDLE_VERSION}" - yq -i ".version = \"${CHART_VERSION}\"" Chart.yaml - yq -i ".appVersion = \"${APP_VERSION}\"" Chart.yaml - echo "OK: Chart.yaml updated" - echo " version (OCI tag): $CHART_VERSION" - echo " appVersion: $APP_VERSION" + + if ! exec_action "Hydrate Chart.yaml" 30 "yq -i '.version = \"${CHART_VERSION}\"' Chart.yaml && yq -i '.appVersion = \"${APP_VERSION}\"' Chart.yaml"; then + echo "ERROR: Failed to update Chart.yaml" + FINAL_EXIT_CODE=1 + exit 1 + fi + echo "│ OK: Chart.yaml updated" + echo "│ version (OCI tag): $CHART_VERSION" + echo "│ appVersion: $APP_VERSION" echo "=== PHASE 7: Hydrating values.yaml ===" - yq -i ".global.targetNamespace = \"v${XY}-openshift-virtualization-tenant\"" values.yaml - yq -i ".global.releasePlan = \"v${XY}-component-releaseplan\"" values.yaml - yq -i ".global.bundleReleasePlan = \"v${XY}-bundle-releaseplan\"" values.yaml - echo "OK: Global values set" + + if [[ ! -f "values.yaml" ]]; then + echo "ERROR: values.yaml not found" + FINAL_EXIT_CODE=1 + exit 1 + fi + + if ! exec_action "Hydrate values.yaml" 30 "yq -i '.global.targetNamespace = \"v${XY}-openshift-virtualization-tenant\"' values.yaml && yq -i '.global.releasePlan = \"v${XY}-component-releaseplan\"' values.yaml && yq -i '.global.bundleReleasePlan = \"v${XY}-bundle-releaseplan\"' values.yaml"; then + echo "ERROR: Failed to update values.yaml" + FINAL_EXIT_CODE=1 + exit 1 + fi + echo "│ OK: Global values set" echo "=== PHASE 8: Injecting snapshots ===" - echo "$SNAPSHOTS_TO_RELEASE" | jq -r '{snapshots: .}' | yq eval -P '.' > /tmp/snapshots_with_key.yaml - yq eval-all '. as $item ireduce ({}; . * $item)' values.yaml /tmp/snapshots_with_key.yaml -i - echo "OK: Snapshots injected into values.yaml" + + # Validate snapshots JSON + if ! echo "$SNAPSHOTS_TO_RELEASE" | jq -e . > /dev/null 2>&1; then + echo "ERROR: Invalid JSON in snapshots-to-release" + FINAL_EXIT_CODE=1 + exit 1 + fi + ACTION_LOG+=("OK|Validate snapshots JSON|exit=0|0s") + + if ! exec_action "Inject snapshots" 30 "echo '$SNAPSHOTS_TO_RELEASE' | jq -r '{snapshots: .}' | yq eval -P '.' > /tmp/snapshots_with_key.yaml && yq eval-all '. as \$item ireduce ({}; . * \$item)' values.yaml /tmp/snapshots_with_key.yaml -i"; then + echo "ERROR: Failed to inject snapshots" + FINAL_EXIT_CODE=1 + exit 1 + fi + echo "│ OK: Snapshots injected into values.yaml" echo "=== PHASE 9: Validating chart ===" - if ! helm lint .; then + if ! exec_action "Lint chart" 30 "helm lint ."; then echo "ERROR: Chart validation failed" + FINAL_EXIT_CODE=1 exit 1 fi - echo "OK: Chart passed validation" + echo "│ OK: Chart passed validation" echo "=== PHASE 10: Packaging chart ===" - helm package . + if ! exec_action "Package chart" 30 "helm package ."; then + echo "ERROR: Failed to package chart" + FINAL_EXIT_CODE=1 + exit 1 + fi + PACKAGE_FILE=$(ls ${CHART_NAME}-*.tgz 2>/dev/null | head -1) if [[ -z "${PACKAGE_FILE}" || ! -f "${PACKAGE_FILE}" ]]; then echo "ERROR: Failed to find packaged chart file" + FINAL_EXIT_CODE=1 exit 1 fi - echo "OK: Packaged as $PACKAGE_FILE" + ACTION_LOG+=("OK|Validate package file|exit=0|0s") + echo "│ OK: Packaged as $PACKAGE_FILE" echo "=== PHASE 11: Pushing to OCI registry ===" - helm push "${PACKAGE_FILE}" "oci://${TARGET_REGISTRY}" + if ! exec_action "Push to OCI registry" 120 "helm push '${PACKAGE_FILE}' 'oci://${TARGET_REGISTRY}'"; then + echo "ERROR: Failed to push chart to registry" + FINAL_EXIT_CODE=1 + exit 1 + fi echo "=== push-release-chart step completed ===" - echo "Published ${CHART_NAME}:${CHART_VERSION} to oci://${TARGET_REGISTRY}" + echo "│ Published ${CHART_NAME}:${CHART_VERSION} to oci://${TARGET_REGISTRY}" + FINAL_EXIT_CODE=0 From 74ef0c9358a14ee37b8c6ea5db71b1f3cc428e9f Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 5 Feb 2026 15:37:51 +0100 Subject: [PATCH 63/88] Fix: export update_images_snapshots function --- pipelines/update-bundle.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 39f70e8..997a93f 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -251,6 +251,7 @@ spec: } echo "=== PHASE 4: Updating image references ===" + export -f update_images_snapshots if ! exec_action "Update image references" 60 "update_images_snapshots"; then echo "ERROR: Failed to update image references" FINAL_EXIT_CODE=1 From 24d98a1a8518da2150058a42df8b3ecb7f35ecd6 Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 5 Feb 2026 16:00:54 +0100 Subject: [PATCH 64/88] Use git status porcelain when checking if there are changes --- pipelines/update-bundle.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 997a93f..b82b1d9 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -259,8 +259,8 @@ spec: fi echo "=== PHASE 5: Committing and pushing changes ===" - git add . - if ! git diff-index --quiet HEAD; then + if [[ -n "$(git status --porcelain)" ]]; then + git add . git commit -m "Update HCO bundle registry with new images" ACTION_LOG+=("OK|Commit changes|exit=0|0s") From d10638be34b357af3579d9b4342eef6e3fd6c9b3 Mon Sep 17 00:00:00 2001 From: thason Date: Thu, 5 Feb 2026 17:02:41 +0200 Subject: [PATCH 65/88] Refactor update-bundle pipeline to improve counter increment syntax for status logging. Replace arithmetic expressions with more explicit increment operations for better readability and maintainability. --- pipelines/update-bundle.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index b82b1d9..a588c18 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -125,9 +125,9 @@ spec: local details=$(echo "$entry" | cut -d'|' -f3-) case "$status" in - OK) ((ok_count++)); echo "║ ✓ $action ($details)" ;; - FAILED) ((fail_count++)); echo "║ ✗ $action ($details)" ;; - TIMEOUT) ((timeout_count++)); echo "║ ⏱ $action ($details)" ;; + OK) ok_count=$((ok_count + 1)); echo "║ ✓ $action ($details)" ;; + FAILED) fail_count=$((fail_count + 1)); echo "║ ✗ $action ($details)" ;; + TIMEOUT) timeout_count=$((timeout_count + 1)); echo "║ ⏱ $action ($details)" ;; esac done @@ -423,9 +423,9 @@ spec: local details=$(echo "$entry" | cut -d'|' -f3-) case "$status" in - OK) ((ok_count++)); echo "║ ✓ $action ($details)" ;; - FAILED) ((fail_count++)); echo "║ ✗ $action ($details)" ;; - TIMEOUT) ((timeout_count++)); echo "║ ⏱ $action ($details)" ;; + OK) ok_count=$((ok_count + 1)); echo "║ ✓ $action ($details)" ;; + FAILED) fail_count=$((fail_count + 1)); echo "║ ✗ $action ($details)" ;; + TIMEOUT) timeout_count=$((timeout_count + 1)); echo "║ ⏱ $action ($details)" ;; esac done From 8e34e70d30f2442ef729b0532eddc8015c985e8b Mon Sep 17 00:00:00 2001 From: thason Date: Thu, 5 Feb 2026 17:03:20 +0200 Subject: [PATCH 66/88] Refactor execution summary function in execution-layer-reference.mdc to enhance counter increment syntax for improved readability and maintainability. --- .cursor/rules/execution-layer-reference.mdc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.cursor/rules/execution-layer-reference.mdc b/.cursor/rules/execution-layer-reference.mdc index ebc9f1e..523fde6 100644 --- a/.cursor/rules/execution-layer-reference.mdc +++ b/.cursor/rules/execution-layer-reference.mdc @@ -87,9 +87,9 @@ execution_summary() { local details=$(echo "$entry" | cut -d'|' -f3-) case "$status" in - OK) ((ok_count++)); echo "║ ✓ $action ($details)" ;; - FAILED) ((fail_count++)); echo "║ ✗ $action ($details)" ;; - TIMEOUT) ((timeout_count++)); echo "║ ⏱ $action ($details)" ;; + OK) ok_count=$((ok_count + 1)); echo "║ ✓ $action ($details)" ;; + FAILED) fail_count=$((fail_count + 1)); echo "║ ✗ $action ($details)" ;; + TIMEOUT) timeout_count=$((timeout_count + 1)); echo "║ ⏱ $action ($details)" ;; esac done From 6f0ef9eb3bcc79c4ee4613c31478c56644f9bfc2 Mon Sep 17 00:00:00 2001 From: thason Date: Thu, 5 Feb 2026 17:11:55 +0200 Subject: [PATCH 67/88] Enhance update-bundle pipeline by defining snapshots_file outside the function for improved accessibility. Export necessary variables and the update_images_snapshots function to ensure proper execution in subshells. --- pipelines/update-bundle.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index a588c18..a0ec442 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -226,6 +226,9 @@ spec: fi echo "│ OK: All components point to the same commit" + # Define snapshots_file outside function so it's available in main script + snapshots_file="components/hco-bundle-registry/snapshots.json" + function update_images_snapshots() { for img in $IMAGES; do image_name_sha=$(echo "${img##*/}") @@ -239,7 +242,6 @@ spec: jq ".\"${image_name}-image\" = \"${image_name_sha}\"" "$json_file" > "${json_file}.tmp" && mv "${json_file}.tmp" "$json_file" done - snapshots_file="components/hco-bundle-registry/snapshots.json" touch ${snapshots_file} jq -n \ --slurpfile f "$snapshots_file" \ @@ -251,7 +253,9 @@ spec: } echo "=== PHASE 4: Updating image references ===" + # Export function AND variables needed by function when run in subshell via exec_action export -f update_images_snapshots + export IMAGES APPLICATION SNAPSHOT_ID snapshots_file if ! exec_action "Update image references" 60 "update_images_snapshots"; then echo "ERROR: Failed to update image references" FINAL_EXIT_CODE=1 From ce3efd8f2f2a71f83e956c54715df4f9e8a22c34 Mon Sep 17 00:00:00 2001 From: thason Date: Fri, 6 Feb 2026 02:41:31 +0200 Subject: [PATCH 68/88] Refactor Quay registry login process in update-bundle pipeline to enhance logging and error handling. Directly capture login output and status, improving visibility into the login process and ensuring better feedback on success or failure. --- pipelines/update-bundle.yaml | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index a0ec442..90328d2 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -530,16 +530,30 @@ spec: ACTION_LOG+=("OK|Extract Quay credentials|exit=0|0s") echo "│ OK: Extracted credentials for user: $QUAY_USERNAME" - if ! exec_action "Login to Quay registry" 30 "echo '***' | helm registry login quay.io --username '${QUAY_USERNAME}' --password-stdin"; then - # Retry with actual password (exec_action masks it) - if ! echo "${QUAY_PASSWORD}" | helm registry login quay.io --username "${QUAY_USERNAME}" --password-stdin; then - echo "ERROR: Failed to login to Quay registry" - FINAL_EXIT_CODE=1 - exit 1 - fi + # Login directly -- password can't be piped through exec_action safely + echo "" + echo "┌─────────────────────────────────────────────────────────────" + echo "│ ACTION: Login to Quay registry" + echo "│ CMD: echo '***' | helm registry login quay.io --username '${QUAY_USERNAME}' --password-stdin" + echo "│ TIMEOUT: 30s" + echo "├─────────────────────────────────────────────────────────────" + login_output=$(echo "${QUAY_PASSWORD}" | timeout 30 helm registry login quay.io --username "${QUAY_USERNAME}" --password-stdin 2>&1) + login_exit=$? + if [[ -n "$login_output" ]]; then + echo "$login_output" | sed 's/^/│ /' + fi + echo "├─────────────────────────────────────────────────────────────" + if [[ $login_exit -eq 0 ]]; then + echo "│ STATUS: OK (exit: 0, duration: 0s)" + echo "└─────────────────────────────────────────────────────────────" + ACTION_LOG+=("OK|Login to Quay registry|exit=0|0s") else - # Actually login with real password - echo "${QUAY_PASSWORD}" | helm registry login quay.io --username "${QUAY_USERNAME}" --password-stdin > /dev/null 2>&1 + echo "│ STATUS: FAILED (exit: $login_exit, duration: 0s)" + echo "└─────────────────────────────────────────────────────────────" + ACTION_LOG+=("FAILED|Login to Quay registry|exit=$login_exit|0s") + echo "ERROR: Failed to login to Quay registry" + FINAL_EXIT_CODE=1 + exit 1 fi echo "│ OK: Logged in to quay.io" From a4f55bc6fa6d8887c2134f6f7db1dbcf5b6eec99 Mon Sep 17 00:00:00 2001 From: thason Date: Fri, 6 Feb 2026 09:43:43 +0200 Subject: [PATCH 69/88] Improve commit consistency validation in update-bundle pipeline by directly checking snapshot data. Enhance logging for validation actions and outcomes, ensuring clearer feedback on component revisions and error handling. Remove temporary snapshot file after processing. --- pipelines/update-bundle.yaml | 60 ++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 90328d2..027a7e9 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -214,17 +214,57 @@ spec: echo "=== PHASE 3: Validating commit consistency ===" IMAGES=$(jq -r '.spec.components[].containerImage' <<< "$SNAPSHOT_DATA") - if ! exec_action "Validate commit consistency" 30 "jq -e '[.spec.components[].source.git.revision] | unique | length == 1' <<< '$SNAPSHOT_DATA' > /dev/null"; then - echo "ERROR: Commits are inconsistent!" - echo "Component revisions:" - jq -r '.spec.components[] | "\(.name): \(.source.git.revision)"' <<< "$SNAPSHOT_DATA" - echo "" - echo "Unique revisions found:" - jq -r '[.spec.components[].source.git.revision] | unique | .[]' <<< "$SNAPSHOT_DATA" + # Check commit consistency directly -- large JSON can't be passed safely through exec_action + echo "" + echo "┌─────────────────────────────────────────────────────────────" + echo "│ ACTION: Validate commit consistency" + echo "│ CMD: jq '[.spec.components[].source.git.revision] | unique | length' /tmp/snapshot.json" + echo "│ TIMEOUT: 30s" + echo "├─────────────────────────────────────────────────────────────" + + echo "$SNAPSHOT_DATA" > /tmp/snapshot.json + consistency_exit=0 + UNIQUE_COUNT=$(jq '[.spec.components[].source.git.revision] | unique | length' /tmp/snapshot.json 2>&1) || consistency_exit=$? + + if [[ $consistency_exit -ne 0 ]]; then + echo "│ ERROR: jq failed to parse snapshot data" | sed 's/^/│ /' + echo "├─────────────────────────────────────────────────────────────" + echo "│ STATUS: FAILED (exit: $consistency_exit, duration: 0s)" + echo "└─────────────────────────────────────────────────────────────" + ACTION_LOG+=("FAILED|Validate commit consistency|exit=$consistency_exit|0s") + FINAL_EXIT_CODE=1 + exit 1 + fi + + COMPONENT_COUNT=$(jq '.spec.components | length' /tmp/snapshot.json) + + if [[ "$UNIQUE_COUNT" -eq 0 ]]; then + echo "│ WARN: Snapshot contains no components" + echo "├─────────────────────────────────────────────────────────────" + echo "│ STATUS: FAILED (exit: 1, duration: 0s)" + echo "└─────────────────────────────────────────────────────────────" + ACTION_LOG+=("FAILED|Validate commit consistency|exit=1|0s") FINAL_EXIT_CODE=1 exit 1 + elif [[ "$UNIQUE_COUNT" -eq 1 ]]; then + echo "│ OK: All $COMPONENT_COUNT components point to the same commit" + echo "├─────────────────────────────────────────────────────────────" + echo "│ STATUS: OK (exit: 0, duration: 0s)" + echo "└─────────────────────────────────────────────────────────────" + ACTION_LOG+=("OK|Validate commit consistency|exit=0|0s") + else + echo "│ INFO: $UNIQUE_COUNT unique revisions across $COMPONENT_COUNT components (expected for multi-component apps)" + echo "│ Component revisions:" + jq -r '.spec.components[] | "│ \(.name): \(.source.git.revision)"' /tmp/snapshot.json + echo "│ Unique revisions:" + jq -r '[.spec.components[].source.git.revision] | unique | .[] | "│ \(.)"' /tmp/snapshot.json + echo "├─────────────────────────────────────────────────────────────" + echo "│ STATUS: OK (exit: 0, duration: 0s)" + echo "└─────────────────────────────────────────────────────────────" + ACTION_LOG+=("OK|Validate commit consistency|exit=0|0s") fi - echo "│ OK: All components point to the same commit" + + rm -f /tmp/snapshot.json # Define snapshots_file outside function so it's available in main script snapshots_file="components/hco-bundle-registry/snapshots.json" @@ -537,8 +577,8 @@ spec: echo "│ CMD: echo '***' | helm registry login quay.io --username '${QUAY_USERNAME}' --password-stdin" echo "│ TIMEOUT: 30s" echo "├─────────────────────────────────────────────────────────────" - login_output=$(echo "${QUAY_PASSWORD}" | timeout 30 helm registry login quay.io --username "${QUAY_USERNAME}" --password-stdin 2>&1) - login_exit=$? + login_exit=0 + login_output=$(echo "${QUAY_PASSWORD}" | timeout 30 helm registry login quay.io --username "${QUAY_USERNAME}" --password-stdin 2>&1) || login_exit=$? if [[ -n "$login_output" ]]; then echo "$login_output" | sed 's/^/│ /' fi From 757b9fc53d892cce6c32168e9066d861640b7123 Mon Sep 17 00:00:00 2001 From: thason Date: Fri, 13 Feb 2026 16:43:01 +0200 Subject: [PATCH 70/88] fix(update-bundle): use deterministic chart filename to prevent skeleton version push Replace non-deterministic `ls | head -1` glob with deterministic filename construction using CHART_VERSION. The glob selected the skeleton .tgz (0.0.0-skeleton) over the hydrated one due to alphabetical sorting. Also adds: - Defense-in-depth cleanup of stale .tgz after helm pull --untar - Post-hydration read-back verification of Chart.yaml version - Observability: success echo now includes actual pushed filename Co-authored-by: Cursor --- pipelines/update-bundle.yaml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 027a7e9..7255f3a 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -612,6 +612,9 @@ spec: exit 1 fi cd "${CHART_NAME}" + # Defense-in-depth: remove stale .tgz left by helm pull --untar + rm -f "../${CHART_NAME}"-*.tgz "${CHART_NAME}"-*.tgz 2>/dev/null || true + ACTION_LOG+=("OK|Cleanup stale tgz archives|exit=0|0s") echo "│ OK: Skeleton chart extracted" echo "=== PHASE 6: Hydrating Chart.yaml ===" @@ -644,6 +647,15 @@ spec: echo "│ version (OCI tag): $CHART_VERSION" echo "│ appVersion: $APP_VERSION" + # Feedback loop: verify Chart.yaml was actually hydrated + ACTUAL_VERSION=$(yq '.version' Chart.yaml | tr -d '"') + if [[ "$ACTUAL_VERSION" != "$CHART_VERSION" ]]; then + echo "ERROR: Chart.yaml hydration verification failed. Expected: $CHART_VERSION, Got: $ACTUAL_VERSION" + FINAL_EXIT_CODE=1 + exit 1 + fi + ACTION_LOG+=("OK|Verify Chart.yaml hydration|exit=0|0s") + echo "=== PHASE 7: Hydrating values.yaml ===" if [[ ! -f "values.yaml" ]]; then @@ -691,7 +703,7 @@ spec: exit 1 fi - PACKAGE_FILE=$(ls ${CHART_NAME}-*.tgz 2>/dev/null | head -1) + PACKAGE_FILE="${CHART_NAME}-${CHART_VERSION}.tgz" if [[ -z "${PACKAGE_FILE}" || ! -f "${PACKAGE_FILE}" ]]; then echo "ERROR: Failed to find packaged chart file" @@ -709,5 +721,5 @@ spec: fi echo "=== push-release-chart step completed ===" - echo "│ Published ${CHART_NAME}:${CHART_VERSION} to oci://${TARGET_REGISTRY}" + echo "│ Published ${CHART_NAME}:${CHART_VERSION} to oci://${TARGET_REGISTRY} (file: ${PACKAGE_FILE})" FINAL_EXIT_CODE=0 From 22113600443bd8511635af376c6b6839517429ff Mon Sep 17 00:00:00 2001 From: thason Date: Fri, 13 Feb 2026 16:46:50 +0200 Subject: [PATCH 71/88] refactor(update-bundle): enhance logging and error handling in snapshot validation Improve logging for snapshot validation actions and outcomes in the update-bundle pipeline. Ensure clearer feedback on component revisions and error handling, while also removing temporary snapshot files after processing for better resource management. --- ...bug-Code_Changes_Review_2026-02-13_1530.md | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 Docs/fix_helm_push_bug-Code_Changes_Review_2026-02-13_1530.md diff --git a/Docs/fix_helm_push_bug-Code_Changes_Review_2026-02-13_1530.md b/Docs/fix_helm_push_bug-Code_Changes_Review_2026-02-13_1530.md new file mode 100644 index 0000000..2a24dd2 --- /dev/null +++ b/Docs/fix_helm_push_bug-Code_Changes_Review_2026-02-13_1530.md @@ -0,0 +1,103 @@ +# Code Changes Review: Fix Helm Chart Push Bug + +**Plan:** `fix_helm_push_bug_d166770e.plan.md` +**Date:** 2026-02-13 +**File:** `pipelines/update-bundle.yaml` +**Diff:** 4 hunks, +15 / -2 lines (net +13) + +--- + +## 1. Developer + Technical Impact Summary + +* **Risk Level:** Low +* **Breaking Changes:** None. The pipeline's external interface is unchanged: + * **Params:** `snapshot`, `skeleton-chart-version`, `debug` -- no change + * **Results:** `snapshots-to-release`, `bundle-version` -- no change + * **Step contract:** Shared `/tekton/results/` volume between steps -- no change + * **Secrets:** `hco-updater-gitlab-token`, `quay-builds-creds` -- no change +* **Behavioral Change (intended):** The OCI push now uses the correct versioned `.tgz` file instead of the stale skeleton archive. Downstream Kargo Warehouses will see correct version tags (e.g., `4.21.1-releases.23`) instead of `0.0.0-skeleton`. + +--- + +## 2. Downstream Impact Analysis + +| Consumer | Location | Impact | Risk | +| :--- | :--- | :--- | :--- | +| `fbc-post-release.yaml` | `fbc/fbc-post-release.yaml` | None -- independent pipeline, does not consume `update-bundle` results | None | +| Kargo Warehouses (OCI watch) | External (Konflux cluster) | **Positive** -- will now detect correct version tags from Quay OCI registry | None (fix restores intended behavior) | +| ArgoCD Sync | External (Konflux cluster) | **Positive** -- promotions triggered by Kargo will use the hydrated chart with correct values | None | +| `pipelines/README.md` | Same repo | No update needed -- documents params/results which are unchanged | None | +| Execution summary output | Pipeline logs | Two new ACTION_LOG entries appear: `Cleanup stale tgz archives`, `Verify Chart.yaml hydration`. Does not affect parsing -- log consumers read exit codes, not action names. | None | + +**Existing tests:** No automated test suite exists for this pipeline (Tekton pipelines are validated via `kubectl apply --dry-run=client` per README). No risk of test failure. + +--- + +## 3. Findings and Fixes + +| File | Line | Severity | Issue Type | Description and Fix | +| :--- | :--- | :--- | :--- | :--- | +| `update-bundle.yaml` | 651 | LOW | Robustness | The `yq` read-back runs under `set -eo pipefail`. If `yq` fails (unlikely since it just wrote to the same file), `set -e` aborts the script but `FINAL_EXIT_CODE` remains `0`, causing the execution summary trap to exit `0`. **This is a pre-existing pattern issue**, not introduced by this change. To harden, wrap with explicit error handling: `ACTUAL_VERSION=$(yq '.version' Chart.yaml \| tr -d '"') \|\| { echo "ERROR: ..."; FINAL_EXIT_CODE=1; exit 1; }`. **Verdict: acceptable as-is** -- the preceding `exec_action` just used `yq -i` on the same file, so a read failure here would indicate a catastrophic environment problem. | +| `update-bundle.yaml` | 708 | LOW | Dead code | The `-z "${PACKAGE_FILE}"` check is now redundant since the variable is constructed from two previously-validated non-empty strings (`CHART_NAME` at line 530 is a constant, `CHART_VERSION` at line 638 is validated at lines 632-636). **Verdict: keep it** -- it costs nothing and provides defense-in-depth if the variable construction logic is ever refactored. | +| `update-bundle.yaml` | 616 | INFO | Style | The `ACTION_LOG` entry for stale `.tgz` cleanup always reports `OK` regardless of whether files were actually removed. This is acceptable since `rm -f` is idempotent and the action's purpose is cleanup, not validation. | + +**No HIGH or CRITICAL issues found.** + +--- + +## 4. Verification Plan + +### Pre-merge (local) + +1. **YAML syntax validation:** + +```bash +python3 -c "import yaml; yaml.safe_load(open('pipelines/update-bundle.yaml'))" +``` + +2. **Bash syntax validation** -- extract the `push-release-chart` script and check: + +```bash +# Extract script block and validate syntax +yq '.spec.tasks[0].taskSpec.steps[1].script' pipelines/update-bundle.yaml > /tmp/push-release-chart.sh +bash -n /tmp/push-release-chart.sh +``` + +3. **Dry-run apply:** + +```bash +kubectl apply --dry-run=client -f pipelines/update-bundle.yaml +``` + +### Post-merge (pipeline run) + +4. **Trigger a test run** against a non-production `hco-bundle-registry` snapshot. In the pipeline log, verify the five-line consistency check: + +``` +ACTION: Package chart --> ...hco-bundle-registry-rhel9-X.Y.Z-releases.N.tgz +OK: Packaged as --> ...hco-bundle-registry-rhel9-X.Y.Z-releases.N.tgz +CMD: helm push --> ...hco-bundle-registry-rhel9-X.Y.Z-releases.N.tgz +Pushed: --> ...hco-bundle-registry-rhel9:X.Y.Z-releases.N +Published --> ...hco-bundle-registry-rhel9:X.Y.Z-releases.N (file: ...) +``` + +All five lines MUST show the same version string. The previously broken run showed `0.0.0-skeleton` on lines 2-5 while line 1 had the correct version. + +5. **Verify Quay OCI tag** -- after the pipeline completes, confirm the chart exists at the expected tag: + +```bash +helm show chart oci://quay.io/openshift-virtualization/konflux-builds/v4-21/hco-bundle-registry-rhel9 --version 4.21.1-releases.23 +``` + +6. **Verify new ACTION_LOG entries** in the execution summary: + +``` +Cleanup stale tgz archives +Verify Chart.yaml hydration +``` + +Both should appear as `OK` in the summary. + +### Regression check + +7. **Non-hco-bundle-registry snapshot:** Run the pipeline with a non-bundle snapshot (e.g., a `kubevirt` component). Verify the `push-release-chart` step correctly skips at Phase 1 with `SKIP: Snapshot does not contain 'hco-bundle-registry'`. This flow is not touched by the changes but confirms no collateral damage. From 57aadad0882de1d5ac915a9a64df55d8b205d1d7 Mon Sep 17 00:00:00 2001 From: Axuba Date: Mon, 16 Feb 2026 17:09:53 +0100 Subject: [PATCH 72/88] If application is a test application, don't update the snapshot file --- pipelines/update-bundle.yaml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 7255f3a..56979f4 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -283,13 +283,17 @@ spec: done touch ${snapshots_file} - jq -n \ - --slurpfile f "$snapshots_file" \ - --arg app "$APPLICATION" \ - --arg snap "$SNAPSHOT_ID" \ - '$f[0] // {} | .[$app] = $snap' \ - > "$snapshots_file.tmp" \ - && mv "$snapshots_file.tmp" "$snapshots_file" + if [[ ! "$APPLICATION" == *"-test-"* ]]; then + jq -n \ + --slurpfile f "$snapshots_file" \ + --arg app "$APPLICATION" \ + --arg snap "$SNAPSHOT_ID" \ + '$f[0] // {} | .[$app] = $snap' \ + > "$snapshots_file.tmp" \ + && mv "$snapshots_file.tmp" "$snapshots_file" + else + echo "Test application, skipping snapshot being added to the bundle, as it won't be released" + fi } echo "=== PHASE 4: Updating image references ===" From ec166f5b82cb8822b13c5e16fc001b5a1d137ea1 Mon Sep 17 00:00:00 2001 From: Axuba Date: Tue, 17 Feb 2026 09:21:17 +0100 Subject: [PATCH 73/88] Fail when revisions differ --- pipelines/update-bundle.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 56979f4..b099b92 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -253,15 +253,17 @@ spec: echo "└─────────────────────────────────────────────────────────────" ACTION_LOG+=("OK|Validate commit consistency|exit=0|0s") else - echo "│ INFO: $UNIQUE_COUNT unique revisions across $COMPONENT_COUNT components (expected for multi-component apps)" + echo "│ WARN: $UNIQUE_COUNT unique revisions across $COMPONENT_COUNT components" echo "│ Component revisions:" jq -r '.spec.components[] | "│ \(.name): \(.source.git.revision)"' /tmp/snapshot.json echo "│ Unique revisions:" jq -r '[.spec.components[].source.git.revision] | unique | .[] | "│ \(.)"' /tmp/snapshot.json echo "├─────────────────────────────────────────────────────────────" - echo "│ STATUS: OK (exit: 0, duration: 0s)" + echo "│ STATUS: FAILED (exit: 1, duration: 0s)" echo "└─────────────────────────────────────────────────────────────" - ACTION_LOG+=("OK|Validate commit consistency|exit=0|0s") + ACTION_LOG+=("FAILED|Validate commit consistency|exit=1|0s") + FINAL_EXIT_CODE=1 + exit 1 fi rm -f /tmp/snapshot.json From 5ba25d0eb2f0d960b5a772e0b28359e4574ad068 Mon Sep 17 00:00:00 2001 From: Tal Hason Date: Tue, 17 Feb 2026 11:24:37 +0200 Subject: [PATCH 74/88] fix(update-bundle): update chart name and refine values.yaml hydration process Change the chart name from 'hco-bundle-registry-rhel9' to 'hco-bundle-registry' for consistency. Additionally, modify the hydration command for values.yaml to update the release plan suffix instead of the bundle release plan, streamlining the configuration process. --- pipelines/update-bundle.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index b099b92..a1021c2 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -533,7 +533,7 @@ spec: echo "│ XY Version: $XY" echo "=== PHASE 3: Loading configuration ===" - CHART_NAME="hco-bundle-registry-rhel9" + CHART_NAME="hco-bundle-registry" SKELETON_REGISTRY="quay.io/openshift-virtualization/release-chart" TARGET_REGISTRY="quay.io/openshift-virtualization/konflux-builds/v${XY}" SKELETON_VERSION="$(params.SKELETON_CHART_VERSION)" @@ -670,7 +670,7 @@ spec: exit 1 fi - if ! exec_action "Hydrate values.yaml" 30 "yq -i '.global.targetNamespace = \"v${XY}-openshift-virtualization-tenant\"' values.yaml && yq -i '.global.releasePlan = \"v${XY}-component-releaseplan\"' values.yaml && yq -i '.global.bundleReleasePlan = \"v${XY}-bundle-releaseplan\"' values.yaml"; then + if ! exec_action "Hydrate values.yaml" 30 "yq -i '.global.targetNamespace = \"v${XY}-openshift-virtualization-tenant\"' values.yaml && yq -i '.global.releasePlanSuffix = \"-releaseplan-prod\"' values.yaml"; then echo "ERROR: Failed to update values.yaml" FINAL_EXIT_CODE=1 exit 1 From fc4436ca486dd6888ab9679ff06b119f142bd53f Mon Sep 17 00:00:00 2001 From: thason Date: Fri, 20 Feb 2026 22:27:18 +0200 Subject: [PATCH 75/88] fix(fbc-post-release): add retry loop for git push race condition --- fbc/fbc-post-release.yaml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 81e38a0..ada6b99 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -128,4 +128,17 @@ spec: git add . git commit -m "Update payload $hco_bundle_version" - git push origin main + + MAX_RETRIES=5 + for attempt in $(seq 1 $MAX_RETRIES); do + if git push origin main; then + echo "Push succeeded on attempt ${attempt}" + break + fi + if [ "$attempt" -eq "$MAX_RETRIES" ]; then + echo "Push failed after ${MAX_RETRIES} attempts" + exit 1 + fi + echo "Push rejected (attempt ${attempt}/${MAX_RETRIES}), rebasing..." + git pull --rebase origin main + done From 2fc3267e8bc43f90fa858856b2904788ce9cc663 Mon Sep 17 00:00:00 2001 From: thason Date: Sun, 22 Feb 2026 10:19:12 +0200 Subject: [PATCH 76/88] delete: remove execution-layer-reference.mdc and tekton-pipelines.mdc files as part of repository cleanup --- ...pipelines.mdc => 010-tekton-pipelines.mdc} | 0 ....mdc => 020-execution-layer-reference.mdc} | 0 .cursor/skills/add-tekton-task/SKILL.md | 125 ++++++++++++++++++ .../skills/validate-tekton-pipeline/SKILL.md | 80 +++++++++++ 4 files changed, 205 insertions(+) rename .cursor/rules/{tekton-pipelines.mdc => 010-tekton-pipelines.mdc} (100%) rename .cursor/rules/{execution-layer-reference.mdc => 020-execution-layer-reference.mdc} (100%) create mode 100644 .cursor/skills/add-tekton-task/SKILL.md create mode 100644 .cursor/skills/validate-tekton-pipeline/SKILL.md diff --git a/.cursor/rules/tekton-pipelines.mdc b/.cursor/rules/010-tekton-pipelines.mdc similarity index 100% rename from .cursor/rules/tekton-pipelines.mdc rename to .cursor/rules/010-tekton-pipelines.mdc diff --git a/.cursor/rules/execution-layer-reference.mdc b/.cursor/rules/020-execution-layer-reference.mdc similarity index 100% rename from .cursor/rules/execution-layer-reference.mdc rename to .cursor/rules/020-execution-layer-reference.mdc diff --git a/.cursor/skills/add-tekton-task/SKILL.md b/.cursor/skills/add-tekton-task/SKILL.md new file mode 100644 index 0000000..a2e0498 --- /dev/null +++ b/.cursor/skills/add-tekton-task/SKILL.md @@ -0,0 +1,125 @@ +--- +name: add-tekton-task +description: Guides adding a new Tekton pipeline task step using the Resilient Execution Layer template. Includes timeout table, validation checklist, and exec_action patterns. Use when adding tasks, creating pipeline steps, or implementing new automation. +--- + +# Add Tekton Task + +## Prerequisites + +Before adding a task, determine: + +1. **Target pipeline** -- `pipelines/update-bundle.yaml`, `fbc/fbc-post-release.yaml`, or new file? +2. **Position** -- Which task does it run after? +3. **External calls** -- What commands does the step invoke (git, helm, kubectl, curl)? + +## Step-by-Step + +### 1. Add the task entry to the pipeline + +```yaml +- name: my-new-task + runAfter: + - + taskSpec: + params: + - name: PARAM_NAME + description: What this param provides + results: + - name: MY_RESULT + description: What this result contains + steps: + - name: run-logic + image: @sha256: + script: | + #!/usr/bin/env bash + # Paste the execution layer template below +``` + +### 2. Apply the execution layer template + +Copy from `.cursor/rules/020-execution-layer-reference.mdc`: + +```bash +#!/usr/bin/env bash + +# ============================================================ +# EXECUTION LAYER +# ============================================================ +SCRIPT_START=$(date +%s) +declare -a ACTION_LOG=() +FINAL_EXIT_CODE=0 + +if [[ "$(params.DEBUG)" == "true" ]]; then set -x; fi + +# (exec_action and execution_summary functions from template) + +trap execution_summary EXIT + +# ============================================================ +# RUN LOGIC +# ============================================================ +set -eo pipefail + +# Your business logic here, using exec_action for external calls +``` + +### 3. Wrap external calls with exec_action + +Use the timeout table for appropriate values: + +| Command Type | Timeout | +|-------------|---------| +| kubectl/oc API calls | 60s | +| git clone | 120s | +| git pull/push | 60s | +| helm pull/push | 120s | +| helm lint/package | 30s | +| Registry login | 30s | +| Validation checks | 30s | + +```bash +if ! exec_action "Clone repository" 120 "git clone \$REPO_URL /workspace/repo"; then + echo "ERROR: Clone failed" + FINAL_EXIT_CODE=1 + exit 1 +fi +``` + +### 4. Write results before exit + +```bash +echo -n "$VALUE" > $(results.MY_RESULT.path) +FINAL_EXIT_CODE=0 +``` + +### 5. Add debug parameter + +Every pipeline MUST have a `debug` param: + +```yaml +params: + - name: debug + type: string + default: "false" + description: Enable debug mode with verbose output (set -x) +``` + +## Validation After Adding + +1. YAML syntax: `python3 -c "import yaml; yaml.safe_load(open('file.yaml'))"` +2. Bash syntax: Extract script, run `bash -n script.sh` +3. Dry-run: `kubectl apply --dry-run=client -f file.yaml` +4. Verify `runAfter` ordering +5. Verify result references use correct task/param names + +## Checklist + +- [ ] Execution layer header (SCRIPT_START, ACTION_LOG, FINAL_EXIT_CODE) +- [ ] exec_action() for all external calls +- [ ] execution_summary() trap set +- [ ] set -eo pipefail after execution layer +- [ ] All params validated (non-empty, files exist) +- [ ] Results written before every exit path +- [ ] Debug param wired through +- [ ] Image pinned with @sha256: digest diff --git a/.cursor/skills/validate-tekton-pipeline/SKILL.md b/.cursor/skills/validate-tekton-pipeline/SKILL.md new file mode 100644 index 0000000..040474d --- /dev/null +++ b/.cursor/skills/validate-tekton-pipeline/SKILL.md @@ -0,0 +1,80 @@ +--- +name: validate-tekton-pipeline +description: Validates Tekton pipeline and task YAML for syntax errors, bash script correctness, and dry-run apply. Use when editing pipelines, adding tasks, modifying scripts, or before committing. +--- + +# Validate Tekton Pipeline + +## When to Use + +- After editing any `pipelines/**/*.yaml` or `fbc/**/*.yaml` file +- After modifying embedded bash scripts in `script:` blocks +- Before committing pipeline changes + +## Quick Validation + +### 1. YAML Syntax Check + +```bash +cd /home/thason/Git/Openshift-virtulization/GitHub/tekton-tasks +python3 -c " +import yaml, sys, pathlib +for f in list(pathlib.Path('pipelines').rglob('*.yaml')) + list(pathlib.Path('fbc').rglob('*.yaml')): + try: + list(yaml.safe_load_all(f.read_text())) + except Exception as e: + print(f'INVALID: {f}: {e}') + sys.exit(1) +print('All YAML files valid') +" +``` + +### 2. Bash Script Syntax Check + +Extract the `script:` block from a YAML file and validate bash syntax: + +```bash +python3 -c " +import yaml, sys +doc = yaml.safe_load(open(sys.argv[1])) +for task in doc.get('spec', {}).get('tasks', []): + ts = task.get('taskSpec', {}) + for step in ts.get('steps', []): + script = step.get('script', '') + if script: + fname = f'/tmp/{step[\"name\"]}.sh' + with open(fname, 'w') as f: + f.write(script) + import subprocess + r = subprocess.run(['bash', '-n', fname], capture_output=True, text=True) + if r.returncode != 0: + print(f'SYNTAX ERROR in step {step[\"name\"]}: {r.stderr}') + sys.exit(1) + print(f'OK: {step[\"name\"]}') +" pipelines/.yaml +``` + +### 3. Dry-Run Apply + +```bash +kubectl apply --dry-run=client -f pipelines/update-bundle.yaml +kubectl apply --dry-run=client -f fbc/fbc-post-release.yaml +``` + +## Execution Layer Checks + +For steps using the Resilient Execution Layer, verify: + +1. `SCRIPT_START`, `ACTION_LOG`, `FINAL_EXIT_CODE` initialized at top +2. `exec_action()` function defined +3. `execution_summary()` function defined +4. `trap execution_summary EXIT` set before business logic +5. `set -eo pipefail` set after execution layer, before business logic + +## Pre-Commit Workflow + +1. Edit the pipeline/task YAML +2. Run YAML syntax check +3. Run bash syntax check on modified scripts +4. Run `kubectl apply --dry-run=client` +5. Commit with format: `(): ` From ed3d04336aba43610dd7f981362abc86d3cfe5d2 Mon Sep 17 00:00:00 2001 From: thason Date: Wed, 25 Feb 2026 10:41:36 +0200 Subject: [PATCH 77/88] fix(update-bundle): enhance chart name hydration logic and update logging Refine the chart name hydration process to derive the OS suffix from the bundle version, ensuring accurate naming for different OS versions. Update logging to reflect the hydrated chart name during the hydration process and improve error handling for verification steps. This change aims to streamline the chart packaging workflow and enhance clarity in the output logs. --- pipelines/update-bundle.yaml | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index a1021c2..5deee17 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -642,21 +642,43 @@ spec: fi CHART_VERSION="${SEMVER}-releases.${RELEASE_NUM}" + + # Derive OS suffix from bundle version for chart name hydration + # Current builds: 4.20.8-rhel9.47 → rhel9; future: rhel10 + # Defensive: legacy/null OS falls back to base CHART_NAME + if [[ "$BUNDLE_VERSION" == *"-"* ]]; then + OS_SUFFIX=$(echo "$BUNDLE_VERSION" | cut -d'-' -f2 | cut -d'.' -f1) + if [[ -n "$OS_SUFFIX" && "$OS_SUFFIX" != "null" ]]; then + HYDRATED_CHART_NAME="${CHART_NAME}-${OS_SUFFIX}" + else + HYDRATED_CHART_NAME="${CHART_NAME}" + fi + else + HYDRATED_CHART_NAME="${CHART_NAME}" + fi + APP_VERSION="v${BUNDLE_VERSION}" - if ! exec_action "Hydrate Chart.yaml" 30 "yq -i '.version = \"${CHART_VERSION}\"' Chart.yaml && yq -i '.appVersion = \"${APP_VERSION}\"' Chart.yaml"; then + if ! exec_action "Hydrate Chart.yaml" 30 "yq -i '.name = \"${HYDRATED_CHART_NAME}\"' Chart.yaml && yq -i '.version = \"${CHART_VERSION}\"' Chart.yaml && yq -i '.appVersion = \"${APP_VERSION}\"' Chart.yaml"; then echo "ERROR: Failed to update Chart.yaml" FINAL_EXIT_CODE=1 exit 1 fi echo "│ OK: Chart.yaml updated" + echo "│ name: $HYDRATED_CHART_NAME" echo "│ version (OCI tag): $CHART_VERSION" echo "│ appVersion: $APP_VERSION" # Feedback loop: verify Chart.yaml was actually hydrated + ACTUAL_NAME=$(yq '.name' Chart.yaml | tr -d '"') ACTUAL_VERSION=$(yq '.version' Chart.yaml | tr -d '"') + if [[ "$ACTUAL_NAME" != "$HYDRATED_CHART_NAME" ]]; then + echo "ERROR: Chart.yaml name hydration failed. Expected: $HYDRATED_CHART_NAME, Got: $ACTUAL_NAME" + FINAL_EXIT_CODE=1 + exit 1 + fi if [[ "$ACTUAL_VERSION" != "$CHART_VERSION" ]]; then - echo "ERROR: Chart.yaml hydration verification failed. Expected: $CHART_VERSION, Got: $ACTUAL_VERSION" + echo "ERROR: Chart.yaml version hydration failed. Expected: $CHART_VERSION, Got: $ACTUAL_VERSION" FINAL_EXIT_CODE=1 exit 1 fi @@ -709,7 +731,7 @@ spec: exit 1 fi - PACKAGE_FILE="${CHART_NAME}-${CHART_VERSION}.tgz" + PACKAGE_FILE="${HYDRATED_CHART_NAME}-${CHART_VERSION}.tgz" if [[ -z "${PACKAGE_FILE}" || ! -f "${PACKAGE_FILE}" ]]; then echo "ERROR: Failed to find packaged chart file" @@ -727,5 +749,5 @@ spec: fi echo "=== push-release-chart step completed ===" - echo "│ Published ${CHART_NAME}:${CHART_VERSION} to oci://${TARGET_REGISTRY} (file: ${PACKAGE_FILE})" + echo "│ Published ${HYDRATED_CHART_NAME}:${CHART_VERSION} to oci://${TARGET_REGISTRY} (file: ${PACKAGE_FILE})" FINAL_EXIT_CODE=0 From 17b73c9be7069e5a4bb19993d39aeadb396e6ae6 Mon Sep 17 00:00:00 2001 From: thason Date: Wed, 25 Feb 2026 11:00:20 +0200 Subject: [PATCH 78/88] docs(tekton-pipelines): add credential patterns and Helm OCI chart lifecycle guidance Enhance documentation for Tekton pipelines by introducing sections on credential patterns for registry authentication and secret injection. Include detailed steps for the Helm OCI chart lifecycle, emphasizing the importance of proper chart hydration and cross-step data sharing. This update aims to improve clarity and best practices for users working with Tekton and Helm. --- .cursor/rules/010-tekton-pipelines.mdc | 36 +++++ .cursor/rules/030-update-bundle-pipeline.mdc | 138 ++++++++++++++++++ .../skills/validate-tekton-pipeline/SKILL.md | 45 +++++- 3 files changed, 218 insertions(+), 1 deletion(-) create mode 100644 .cursor/rules/030-update-bundle-pipeline.mdc diff --git a/.cursor/rules/010-tekton-pipelines.mdc b/.cursor/rules/010-tekton-pipelines.mdc index bb12081..23695d2 100644 --- a/.cursor/rules/010-tekton-pipelines.mdc +++ b/.cursor/rules/010-tekton-pipelines.mdc @@ -66,6 +66,42 @@ Use box-drawing characters for structured output: - `║` Summary lines - `╚═════` Summary footer +### Credential Patterns + +#### Registry Auth (Quay OCI) + +For steps that pull/push OCI artifacts (Helm charts, images): +1. Mount the docker config secret as a **volume** (provides `.dockerconfigjson` file) +2. Extract username/password via `jq` from the mounted file +3. Run `helm registry login ` **inline** (not through `exec_action`) -- passwords cannot be safely piped through `bash -c` +4. A single `helm registry login quay.io` covers ALL quay.io repos the robot has access to + +#### Secret Injection + +- Use `envFrom` for tokens needed as env vars (e.g., `GITLAB_TOKEN`) +- Use `volumeMounts` for structured credentials (e.g., `.dockerconfigjson`) +- Never hardcode credentials in pipeline YAML + +### Helm OCI Chart Lifecycle + +When pipelines produce Helm charts via OCI: + +1. **Pull** a skeleton (template) chart from OCI registry +2. **Hydrate** Chart.yaml fields (name, version, appVersion) from build metadata +3. **Hydrate** values.yaml with runtime configuration +4. **Lint** the hydrated chart (`helm lint .`) +5. **Package** (`helm package .`) -- filename is `{Chart.yaml name}-{Chart.yaml version}.tgz` +6. **Push** to target OCI registry (`helm push oci://`) + +`helm package` derives the .tgz filename from `Chart.yaml`, not from shell variables. Always verify `PACKAGE_FILE` matches what `helm package` actually produces. + +### Cross-Step Data Sharing + +Steps within the same Tekton task share `/tekton/results/`: +- Step N writes: `echo -n "$VALUE" > /tekton/results/` +- Step N+1 reads: `cat /tekton/results/` +- Size limit: ~4KB per result, ~12KB total. Monitor for large JSON payloads. + ## File Structure ``` diff --git a/.cursor/rules/030-update-bundle-pipeline.mdc b/.cursor/rules/030-update-bundle-pipeline.mdc new file mode 100644 index 0000000..46ada6a --- /dev/null +++ b/.cursor/rules/030-update-bundle-pipeline.mdc @@ -0,0 +1,138 @@ +--- +description: Architecture and data flow for the update-bundle pipeline (OCI chart lifecycle, cross-step communication, credential management) +globs: "pipelines/update-bundle.yaml" +alwaysApply: false +--- + +# update-bundle Pipeline Architecture + +## Pipeline Overview + +The `update-bundle` pipeline processes HCO bundle registry snapshots from Konflux. It has **two steps** in a single Tekton task, sharing data via `/tekton/results/`. + +## Step Architecture + +``` +Step 1: update-bundle Step 2: push-release-chart +┌──────────────────────────┐ ┌──────────────────────────────┐ +│ Phase 1: Fetch snapshot │ │ Phase 1: Check snapshot type │ +│ Phase 2: Clone repo │ │ Phase 2: Read results │ +│ Phase 3: Validate commit │ │ Phase 3: Load configuration │ +│ Phase 4: Update images │ │ Phase 4: Registry login │ +│ Phase 5: Commit & push │ │ Phase 5: Pull skeleton chart │ +│ Phase 6: Prepare release │──results──▶ │ Phase 6: Hydrate Chart.yaml │ +│ data │ │ Phase 7: Hydrate values.yaml │ +└──────────────────────────┘ │ Phase 8: Inject snapshots │ + │ Phase 9: Lint chart │ + Results written: │ Phase 10: Package chart │ + - bundle-version │ Phase 11: Push to OCI │ + - snapshots-to-release └──────────────────────────────┘ +``` + +## Cross-Step Data Flow + +Steps share data via Tekton results at `/tekton/results/`: + +| Result | Producer | Consumer | Format | Size Risk | +|--------|----------|----------|--------|-----------| +| `bundle-version` | Step 1 Phase 6 | Step 2 Phase 2 | Plain text (`4.20.8-rhel9.47`) | None | +| `snapshots-to-release` | Step 1 Phase 6 | Step 2 Phase 8 | JSON object | Monitor: Tekton limits results to ~4KB each | + +Step 2 gates on snapshot type at Phase 1: if the snapshot name does not contain `hco-bundle-registry`, the step exits 0 immediately. + +## Credential Management + +### Secrets + +| Secret Name | Type | Used By | Purpose | +|-------------|------|---------|---------| +| `hco-updater-gitlab-token` | envFrom | Both steps | GitLab API token (`GITLAB_TOKEN` env var) | +| `quay-builds-creds` | envFrom + volumeMount | Step 2 | Quay robot account credentials | + +### Quay Auth Pattern (Step 2) + +The `quay-builds-creds` secret is both: +1. **Volume-mounted** at `/tmp/quay-builds-creds` (provides `.dockerconfigjson` file) +2. **Injected via envFrom** (keys become env vars; `.dockerconfigjson` is skipped as invalid env name) + +The script reads credentials from the volume mount, NOT the env vars: +``` +Volume mount → read .dockerconfigjson → jq extract username/password → helm registry login quay.io +``` + +The login is done **inline** (not through `exec_action`) because the password cannot be safely piped through `bash -c`. A single `helm registry login quay.io` covers ALL quay.io repositories. + +### Robot Account + +- Name: `openshift-virtualization+konflux_builds_bot` +- Has write access to: `quay.io/openshift-virtualization/konflux-builds/v{XY}/*` +- Has read access to: `quay.io/openshift-virtualization/release-chart/*` + +## OCI Chart Lifecycle (Skeleton → Hydrate → Push) + +### Design Principle + +The **skeleton chart** is OS-agnostic (`name: hco-bundle-registry`). The **hydrated chart** inherits the OS suffix from the bundle version, producing OS-specific artifacts. + +### Skeleton Chart + +- Registry: `quay.io/openshift-virtualization/release-chart/hco-bundle-registry` +- Version: `0.0.0-skeleton` (configurable via pipeline param) +- Contains: Chart.yaml, values.yaml, templates/ with placeholder values + +### Chart Name Hydration + +The chart name is derived from `BUNDLE_VERSION`: + +``` +BUNDLE_VERSION OS_SUFFIX HYDRATED_CHART_NAME +4.20.8-rhel9.47 → rhel9 → hco-bundle-registry-rhel9 +4.22.1-rhel10.5 → rhel10 → hco-bundle-registry-rhel10 +4.12.36 (legacy) → (none) → hco-bundle-registry +``` + +Extraction: `cut -d'-' -f2 | cut -d'.' -f1` with defensive guards for null/empty. + +### Hydration Fields + +| Chart.yaml Field | Source | Example | +|------------------|--------|---------| +| `name` | `CHART_NAME` + OS suffix | `hco-bundle-registry-rhel9` | +| `version` | `SEMVER-releases.RELEASE_NUM` | `4.20.8-releases.47` | +| `appVersion` | `v` + BUNDLE_VERSION | `v4.20.8-rhel9.47` | + +### Push Destination + +``` +oci://quay.io/openshift-virtualization/konflux-builds/v{XY}/{HYDRATED_CHART_NAME}:{CHART_VERSION} +``` + +Example: `oci://quay.io/openshift-virtualization/konflux-builds/v4-20/hco-bundle-registry-rhel9:4.20.8-releases.47` + +## Variable Derivation Map + +``` +BUNDLE_VERSION = "4.20.8-rhel9.47" (from build-bundle.json → Tekton result) + │ + ├──▶ SEMVER = "4.20.8" (cut -d'-' -f1) + ├──▶ RELEASE_NUM = "47" (grep -oE '[0-9]+$') + ├──▶ OS_SUFFIX = "rhel9" (cut -d'-' -f2 | cut -d'.' -f1) + ├──▶ XY = "4-20" (cut -d'.' -f1,2 | tr '.' '-') + │ + ├──▶ CHART_VERSION = "4.20.8-releases.47" + ├──▶ HYDRATED_CHART_NAME = "hco-bundle-registry-rhel9" + ├──▶ APP_VERSION = "v4.20.8-rhel9.47" + └──▶ TARGET_REGISTRY = "quay.io/openshift-virtualization/konflux-builds/v4-20" +``` + +## Known Gotchas + +1. **Double kubectl fetch (Step 1, Phase 1)**: The snapshot is fetched once via `exec_action` (for logging) and once directly (for data capture). `exec_action` runs in a subshell so its output cannot be captured by the caller. Future fix: write output to a temp file. + +2. **Token in git clone log (Step 1, Phase 2)**: `REPO_URL_WITH_AUTH` embeds the GitLab token and is logged by `exec_action`'s CMD line. Consider sanitizing the display URL. + +3. **jq null OS field**: The jq expression at Step 1 line 345 always produces a dash (`X.Y.Z-{os}.{release}`). If `.os` is null in `build-bundle.json`, BUNDLE_VERSION becomes `4.12.36-null.36`. The hydration code guards against `OS_SUFFIX == "null"`. + +4. **Tekton result size limit**: Individual results are capped at ~4KB. If `snapshots-to-release` JSON grows large (many components), it may exceed this. Monitor snapshot counts. + +5. **exec_action subshell environment**: `exec_action` runs commands via `timeout ... bash -c "..."`. The child process inherits `HOME` and all exported vars, but does NOT have access to unexported shell functions. Use `export -f` when passing functions. diff --git a/.cursor/skills/validate-tekton-pipeline/SKILL.md b/.cursor/skills/validate-tekton-pipeline/SKILL.md index 040474d..81b7ff6 100644 --- a/.cursor/skills/validate-tekton-pipeline/SKILL.md +++ b/.cursor/skills/validate-tekton-pipeline/SKILL.md @@ -71,10 +71,53 @@ For steps using the Resilient Execution Layer, verify: 4. `trap execution_summary EXIT` set before business logic 5. `set -eo pipefail` set after execution layer, before business logic +## Helm OCI Chart Lifecycle Checks + +For steps that hydrate and push Helm charts (e.g., `push-release-chart`): + +### Variable Derivation Chain + +Verify the derivation from `BUNDLE_VERSION` is consistent: + +``` +BUNDLE_VERSION → SEMVER (cut -d'-' -f1) + → RELEASE_NUM (grep -oE '[0-9]+$') + → OS_SUFFIX (cut -d'-' -f2 | cut -d'.' -f1) + → XY (cut -d'.' -f1,2 | tr '.' '-') +``` + +### Chart Name Hydration Contract + +1. `HYDRATED_CHART_NAME` must match what `yq` writes to `.name` in Chart.yaml +2. `CHART_VERSION` must match what `yq` writes to `.version` in Chart.yaml +3. `PACKAGE_FILE` must equal `{HYDRATED_CHART_NAME}-{CHART_VERSION}.tgz` +4. `helm package .` produces the .tgz using `.name` and `.version` from Chart.yaml +5. `helm push` reads the chart name from inside the .tgz for the OCI repo path + +If any of these are misaligned, the package file check (`! -f "${PACKAGE_FILE}"`) will fail, or the push will target the wrong OCI repo. + +### Verification Checklist + +- [ ] Chart.yaml `.name` is hydrated (not left as skeleton default) +- [ ] Chart.yaml `.version` is hydrated (not `0.0.0-skeleton`) +- [ ] Chart.yaml `.appVersion` is hydrated +- [ ] Verification reads back `.name` and `.version` and compares +- [ ] `PACKAGE_FILE` uses `HYDRATED_CHART_NAME`, not `CHART_NAME` +- [ ] Published message uses `HYDRATED_CHART_NAME` +- [ ] OS suffix guard handles: normal (`rhel9`), future (`rhel10`), null, empty, legacy (no dash) + +### Cross-Step Result Checks + +- [ ] Step 1 writes `bundle-version` and `snapshots-to-release` to `/tekton/results/` +- [ ] Step 2 validates both files exist before reading +- [ ] Step 2 validates `bundle-version` is non-empty +- [ ] `snapshots-to-release` JSON is validated with `jq -e .` before injection + ## Pre-Commit Workflow 1. Edit the pipeline/task YAML 2. Run YAML syntax check 3. Run bash syntax check on modified scripts 4. Run `kubectl apply --dry-run=client` -5. Commit with format: `(): ` +5. Verify chart hydration contract (if modifying push-release-chart step) +6. Commit with format: `(): ` From e323e8a531d48ca6a17061640626d32e1d3c8970 Mon Sep 17 00:00:00 2001 From: thason Date: Thu, 26 Feb 2026 13:09:47 +0200 Subject: [PATCH 79/88] feat(pipeline): persist Snapshot objects in chart for GC resilience Save stripped Snapshot YAMLs per-Application during component builds, copy them into the Helm chart templates/ directory during hydration. Helm renders them verbatim into manifests.yaml alongside Release CRs. - Strip only ownerReferences (validated against KubeArchive restore) - Add velero.io/restore-name label to prevent Integration Service from re-processing restored Snapshots - Shared emptyDir volume for inter-step data transfer - Non-fatal on save failure (graceful degradation) CNV-80628 Made-with: Cursor --- pipelines/update-bundle.yaml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 5deee17..b267236 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -41,12 +41,17 @@ spec: - name: quay-creds secret: secretName: quay-builds-creds + - name: shared-data + emptyDir: {} steps: - name: update-bundle image: quay.io/konflux-ci/release-service-utils@sha256:2f9e6863e82bbc9ddce5a290f3fd0e87657c475e3de8a832b2ef7f8d0671e7d3 envFrom: - secretRef: name: hco-updater-gitlab-token + volumeMounts: + - name: shared-data + mountPath: /var/shared script: | #!/usr/bin/env bash @@ -268,6 +273,15 @@ spec: rm -f /tmp/snapshot.json + # Save Snapshot object for GC resilience (stripped, with velero label) + if [[ "$APPLICATION" != *"-test-"* ]]; then + snapshot_objects_dir="components/hco-bundle-registry/snapshot-objects" + mkdir -p "$snapshot_objects_dir" + if ! exec_action "Save Snapshot object for ${APPLICATION}" 30 "set -o pipefail; kubectl get snapshot '$SNAPSHOT_ID' -oyaml | yq 'del(.metadata.ownerReferences) | .metadata.labels[\"velero.io/restore-name\"] = \"snapshot-persistence\"' > '${snapshot_objects_dir}/${APPLICATION}.yaml'"; then + echo "WARN: Failed to save Snapshot object for ${APPLICATION} (non-fatal)" + fi + fi + # Define snapshots_file outside function so it's available in main script snapshots_file="components/hco-bundle-registry/snapshots.json" @@ -331,6 +345,10 @@ spec: echo "│ SKIP: No changes detected in the bundle registry" fi + # Copy Snapshot objects to shared volume for push-release-chart step + mkdir -p /var/shared/snapshot-objects + cp components/hco-bundle-registry/snapshot-objects/*.yaml /var/shared/snapshot-objects/ 2>/dev/null || true + if [[ "$(params.SNAPSHOT)" == *"hco-bundle-registry"* ]]; then echo "=== PHASE 6: Preparing release data for hco-bundle-registry ===" REPO_REVISION=$(jq -r '.spec.components[0].source.git.revision' <<< "$SNAPSHOT_DATA") @@ -395,6 +413,8 @@ spec: - name: quay-creds mountPath: /tmp/quay-builds-creds readOnly: true + - name: shared-data + mountPath: /var/shared script: | #!/usr/bin/env bash @@ -716,6 +736,18 @@ spec: fi echo "│ OK: Snapshots injected into values.yaml" + echo "=== PHASE 8b: Injecting Snapshot objects into chart ===" + SNAPSHOT_OBJECTS_SRC="/var/shared/snapshot-objects" + if ls "${SNAPSHOT_OBJECTS_SRC}"/*.yaml 1>/dev/null 2>&1; then + cp "${SNAPSHOT_OBJECTS_SRC}"/*.yaml templates/ + SNAP_COUNT=$(ls "${SNAPSHOT_OBJECTS_SRC}"/*.yaml 2>/dev/null | wc -l) + echo "│ Copied $SNAP_COUNT Snapshot files into chart templates/" + ACTION_LOG+=("OK|Inject Snapshot objects ($SNAP_COUNT files)|exit=0|0s") + else + echo "│ WARN: No Snapshot object files found" + ACTION_LOG+=("OK|Skip Snapshot objects (none found)|exit=0|0s") + fi + echo "=== PHASE 9: Validating chart ===" if ! exec_action "Lint chart" 30 "helm lint ."; then echo "ERROR: Chart validation failed" From 5282662c41c0c48c883d1eb1a2c284a78603f513 Mon Sep 17 00:00:00 2001 From: thason Date: Tue, 10 Mar 2026 01:02:18 +0200 Subject: [PATCH 80/88] feat(fbc-post-release): add Smartsheet prod release tracking per channel --- fbc/fbc-post-release.yaml | 196 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index ada6b99..39fa2f7 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -35,6 +35,13 @@ spec: type: string - name: ENVIRONMENT type: string + results: + - name: channel + description: Release channel (candidate or stable) + - name: environment + description: Release environment (stage or production) + - name: hco-bundle-version + description: Full bundle version from updated_image.yaml steps: - name: get-info image: quay.io/konflux-ci/release-service-utils:0a58b6a6b562879e89395636d97931f2dcbb494c @@ -142,3 +149,192 @@ spec: echo "Push rejected (attempt ${attempt}/${MAX_RETRIES}), rebasing..." git pull --rebase origin main done + + echo -n "${channel}" > /tekton/results/channel + echo -n "$(params.ENVIRONMENT)" > /tekton/results/environment + echo -n "${hco_bundle_version}" > /tekton/results/hco-bundle-version + - name: update-smartsheet + image: quay.io/konflux-ci/release-service-utils@sha256:dd7fa6a8d8ade6fbc3ad30d974bb72cdefbdf7fd6a9eafa19c09d0146ece67c1 + env: + - name: SMARTSHEET_TOKEN + valueFrom: + secretKeyRef: + name: smartsheets + key: token + optional: true + - name: SHEET_ID + valueFrom: + secretKeyRef: + name: smartsheets + key: SheetId + optional: true + script: | + #!/usr/bin/env bash + set -u + + ENVIRONMENT=$(cat /tekton/results/environment) + if [[ "$ENVIRONMENT" != "production" ]]; then + echo "Skipping Smartsheet update: environment is '${ENVIRONMENT}', not 'production'" + exit 0 + fi + + CHANNEL=$(cat /tekton/results/channel) + HCO_BUNDLE_VERSION=$(cat /tekton/results/hco-bundle-version) + + echo "=== FBC Prod Release Smartsheet Update ===" + echo "Environment: $ENVIRONMENT" + echo "Channel: $CHANNEL" + echo "Bundle: $HCO_BUNDLE_VERSION" + echo "" + + fail_safe() { + echo "" + echo "╔═════════════════════════════════════════" + echo "║ WARN: Smartsheet update failed" + echo "║ Reason: $1" + echo "║ Channel: ${CHANNEL:-unknown}" + echo "║ Bundle: ${HCO_BUNDLE_VERSION:-unknown}" + echo "║ Payload git push was NOT affected" + echo "╚═════════════════════════════════════════" + exit 0 + } + + if [[ -z "${SMARTSHEET_TOKEN:-}" || -z "${SHEET_ID:-}" ]]; then + fail_safe "smartsheets secret not configured (missing token or SheetId)" + fi + + VERSION=$(echo "$HCO_BUNDLE_VERSION" | grep -oP 'v?\d+\.\d+' | head -1) + if [[ -z "$VERSION" ]]; then + fail_safe "Could not derive version from $HCO_BUNDLE_VERSION" + fi + + BUNDLE_ID_VALUE=$(echo "$HCO_BUNDLE_VERSION" | sed 's/-\(rhel[0-9]*\)\./.\1-/') + echo "Version row: $VERSION" + echo "BundleID: $BUNDLE_ID_VALUE" + echo "" + + smartsheet_api_call() { + local METHOD="$1" ENDPOINT="$2" DATA="${3:-}" + local MAX_RETRIES=3 RETRY_DELAY=2 + + for ((i=1; i<=MAX_RETRIES; i++)); do + local CURL_ARGS=(-s -w "\n%{http_code}" -X "$METHOD" + "https://api.smartsheet.com/2.0${ENDPOINT}" + -H "Authorization: Bearer ${SMARTSHEET_TOKEN}" + -H "Content-Type: application/json") + [[ -n "$DATA" ]] && CURL_ARGS+=(-d "$DATA") + + RESPONSE=$(curl "${CURL_ARGS[@]}" 2>/dev/null) + HTTP_CODE=$(echo "$RESPONSE" | tail -1) + BODY=$(echo "$RESPONSE" | sed '$d') + + case "$HTTP_CODE" in + 200|201) echo "$BODY"; return 0 ;; + 429) + echo "WARN: Rate limited, waiting ${RETRY_DELAY}s (attempt $i/$MAX_RETRIES)" >&2 + sleep "$RETRY_DELAY"; RETRY_DELAY=$((RETRY_DELAY * 2)) ;; + 401|403) + echo "ERROR: Auth failed (HTTP $HTTP_CODE)" >&2; return 1 ;; + *) + echo "WARN: API error $HTTP_CODE (attempt $i/$MAX_RETRIES)" >&2 + sleep "$RETRY_DELAY"; RETRY_DELAY=$((RETRY_DELAY * 2)) ;; + esac + done + echo "ERROR: Max retries exceeded" >&2; return 1 + } + + echo "Discovering Smartsheet columns..." + COLUMNS_JSON=$(smartsheet_api_call "GET" "/sheets/${SHEET_ID}/columns" "") \ + || fail_safe "Column discovery failed" + + COL_NAME=$(echo "$COLUMNS_JSON" | jq -r '.data[] | select(.title=="Name") | .id') + COL_BUNDLEID=$(echo "$COLUMNS_JSON" | jq -r '.data[] | select(.title=="BundleID") | .id') + COL_CANDIDATE_PROD=$(echo "$COLUMNS_JSON" | jq -r '.data[] | select(.title=="Candidate Prod") | .id') + COL_CANDIDATE_DATE=$(echo "$COLUMNS_JSON" | jq -r '.data[] | select(.title=="Candidate Prod Date") | .id') + COL_STABLE_PROD=$(echo "$COLUMNS_JSON" | jq -r '.data[] | select(.title=="Stable Prod") | .id') + COL_STABLE_DATE=$(echo "$COLUMNS_JSON" | jq -r '.data[] | select(.title=="Stable Prod Date") | .id') + + if [[ -z "$COL_NAME" || "$COL_NAME" == "null" ]]; then + fail_safe "Primary column 'Name' not found" + fi + if [[ -z "$COL_BUNDLEID" || "$COL_BUNDLEID" == "null" ]]; then + fail_safe "Column 'BundleID' not found" + fi + + case "$CHANNEL" in + "candidate") + COL_PROD="$COL_CANDIDATE_PROD" + COL_DATE="$COL_CANDIDATE_DATE" + ;; + "stable") + COL_PROD="$COL_STABLE_PROD" + COL_DATE="$COL_STABLE_DATE" + ;; + *) + fail_safe "Unknown channel: $CHANNEL" + ;; + esac + + if [[ -z "$COL_PROD" || "$COL_PROD" == "null" ]]; then + fail_safe "Column '${CHANNEL^} Prod' not found -- add it to the Smartsheet first" + fi + if [[ -z "$COL_DATE" || "$COL_DATE" == "null" ]]; then + fail_safe "Column '${CHANNEL^} Prod Date' not found -- add it to the Smartsheet first" + fi + echo "Column IDs discovered" + + SHEET_DATA=$(smartsheet_api_call "GET" "/sheets/${SHEET_ID}" "") \ + || fail_safe "Failed to fetch sheet data" + + VERSION_ROW_ID=$(echo "$SHEET_DATA" | jq -r --arg v "$VERSION" --argjson c "$COL_NAME" \ + '[.rows[]? | select(.parentId == null) | + select(.cells[]? | select(.columnId == $c and .value == $v))] | first | .id // empty') + + if [[ -z "$VERSION_ROW_ID" || "$VERSION_ROW_ID" == "null" ]]; then + fail_safe "Version row '$VERSION' not found in build sheet" + fi + echo "Found L0 version row: $VERSION_ROW_ID" + + APP_ROW_ID=$(echo "$SHEET_DATA" | jq -r --arg app "hco-bundle-registry" --argjson c "$COL_NAME" --argjson pid "$VERSION_ROW_ID" \ + '[.rows[]? | select(.parentId == $pid) | + select(.cells[]? | select(.columnId == $c and .value == $app))] | first | .id // empty') + + if [[ -z "$APP_ROW_ID" || "$APP_ROW_ID" == "null" ]]; then + fail_safe "Application row 'hco-bundle-registry' not found under '$VERSION'" + fi + echo "Found L1 application row: $APP_ROW_ID" + + COMPONENT_ROW_ID=$(echo "$SHEET_DATA" | jq -r \ + --arg bid "$BUNDLE_ID_VALUE" \ + --argjson cb "$COL_BUNDLEID" \ + --argjson pid "$APP_ROW_ID" \ + '[.rows[]? | select(.parentId == $pid) | + select(.cells[]? | select(.columnId == $cb and .value == $bid))] | first | .id // empty') + + if [[ -z "$COMPONENT_ROW_ID" || "$COMPONENT_ROW_ID" == "null" ]]; then + fail_safe "No build row with BundleID '$BUNDLE_ID_VALUE' found under hco-bundle-registry" + fi + echo "Found L2 component row: $COMPONENT_ROW_ID (BundleID: $BUNDLE_ID_VALUE)" + + TIMESTAMP=$(date -Iseconds) + UPDATE_DATA=$(jq -n \ + --argjson rid "$COMPONENT_ROW_ID" \ + --argjson cp "$COL_PROD" \ + --argjson cd "$COL_DATE" \ + --arg date "$TIMESTAMP" \ + '[{id: $rid, cells: [ + {columnId: $cp, value: true}, + {columnId: $cd, value: $date} + ]}]') + + smartsheet_api_call "PUT" "/sheets/${SHEET_ID}/rows" "$UPDATE_DATA" >/dev/null \ + || fail_safe "Failed to update Smartsheet row" + + echo "" + echo "╔═════════════════════════════════════════" + echo "║ FBC Prod Release marked in Smartsheet" + echo "║ Version: $VERSION" + echo "║ Bundle: $HCO_BUNDLE_VERSION" + echo "║ Channel: $CHANNEL" + echo "║ Column: ${CHANNEL^} Prod = true" + echo "╚═════════════════════════════════════════" From e4524e0d4c006b95c153057c665e4b159fec9c85 Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 12 Mar 2026 15:55:08 +0100 Subject: [PATCH 81/88] Virt-platform-autopilot should also be in the core-params --- pipelines/update-bundle.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index b267236..bb6c9b6 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -290,7 +290,8 @@ spec: image_name_sha=$(echo "${img##*/}") image_name=$(echo "$image_name_sha" | cut -d'@' -f1) - if [[ "$image_name" == *"-operator-rhel"* ]]; then + # Virt-platform-autopilot should also be in the core-params + if [[ "$image_name" == *"-operator-rhel"* || "$image_name" == *"virt-platform-autopilot"* ]]; then json_file="components/hco-bundle-registry/core-params.json" else json_file="components/hco-bundle-registry/extra-params.json" From 803507d56473bdeaa98da2607049b6dcdc324f33 Mon Sep 17 00:00:00 2001 From: thason Date: Tue, 17 Mar 2026 13:18:49 +0200 Subject: [PATCH 82/88] feat(report-fbc-build-status): add new task for reporting FBC build status to Smartsheet This commit introduces a new Tekton task that reports the FBC catalog build status to Smartsheet. The task updates existing hco-bundle-registry L2 rows with relevant build information, including the FBC stage, production status, pipeline run name, and channel. It includes a resilient execution layer for observability and error handling, ensuring that the build process does not fail even if certain actions encounter issues. --- fbc/report-fbc-build-status.yaml | 407 +++++++++++++++++++++++++++++++ 1 file changed, 407 insertions(+) create mode 100644 fbc/report-fbc-build-status.yaml diff --git a/fbc/report-fbc-build-status.yaml b/fbc/report-fbc-build-status.yaml new file mode 100644 index 0000000..f3b3761 --- /dev/null +++ b/fbc/report-fbc-build-status.yaml @@ -0,0 +1,407 @@ +# fbc/report-fbc-build-status.yaml +# @ai-rules: +# 1. [Pattern]: Resilient Execution Layer — exec_action, execution_summary, trap. +# 2. [Constraint]: FINAL_EXIT_CODE=0 always — this is a fail-safe task, never fail the build. +# 3. [Pattern]: Secret is `smartsheets` (keys: token, SheetId), same as fbc-post-release.yaml. +# 4. [Gotcha]: BundleID in commit message is already in sheet format — no sed transform needed. +# 5. [Gotcha]: L0 version rows use `v4.21` format (keep `v` prefix). +apiVersion: tekton.dev/v1 +kind: Task +metadata: + name: report-fbc-build-status + annotations: + description: | + Reports FBC catalog build status to Smartsheet by updating existing hco-bundle-registry + L2 rows with FBC Stage/Prod status, PipelineRun name, and channel. + Referenced via git resolver from fbc-pipeline finally block. +spec: + params: + - name: git-url + type: string + - name: revision + type: string + - name: pipelinerun-name + type: string + - name: pipelinerun-namespace + type: string + - name: PIPELINE_AGGREGATE_STATUS + type: string + - name: DEBUG + type: string + default: "false" + steps: + - name: post-fbc-status + image: quay.io/konflux-ci/release-service-utils@sha256:dd7fa6a8d8ade6fbc3ad30d974bb72cdefbdf7fd6a9eafa19c09d0146ece67c1 + env: + - name: SMARTSHEET_TOKEN + valueFrom: + secretKeyRef: + name: smartsheets + key: token + optional: true + - name: SHEET_ID + valueFrom: + secretKeyRef: + name: smartsheets + key: SheetId + optional: true + script: | + #!/usr/bin/env bash + + # ============================================================ + # EXECUTION LAYER - Resilient wrapper for observability + # ============================================================ + SCRIPT_START=$(date +%s) + declare -a ACTION_LOG=() + FINAL_EXIT_CODE=0 + + if [[ "$(params.DEBUG)" == "true" ]]; then set -x; fi + + exec_action() { + local action_name="$1" + local timeout_secs="${2:-60}" + shift 2 + local cmd="$*" + + local start_ts=$(date +%s) + echo "" + echo "┌─────────────────────────────────────────────────────────────" + echo "│ ACTION: $action_name" + echo "│ TIMEOUT: ${timeout_secs}s" + echo "├─────────────────────────────────────────────────────────────" + + local output exit_code + output=$(timeout "$timeout_secs" bash -c "$cmd" 2>&1) + exit_code=$? + + local end_ts=$(date +%s) + local duration=$((end_ts - start_ts)) + + if [[ -n "$output" ]]; then + echo "$output" | sed 's/^/│ /' + fi + + local status + if [[ $exit_code -eq 0 ]]; then + status="OK" + elif [[ $exit_code -eq 124 ]]; then + status="TIMEOUT" + else + status="FAILED" + fi + + echo "├─────────────────────────────────────────────────────────────" + echo "│ STATUS: $status (exit: $exit_code, duration: ${duration}s)" + echo "└─────────────────────────────────────────────────────────────" + + ACTION_LOG+=("$status|$action_name|exit=$exit_code|${duration}s") + return $exit_code + } + + execution_summary() { + local script_end=$(date +%s) + local total_duration=$((script_end - SCRIPT_START)) + + echo "" + echo "╔═════════════════════════════════════════════════════════════" + echo "║ EXECUTION SUMMARY - report-fbc-build-status" + echo "║ Total Duration: ${total_duration}s" + echo "║ Final Exit Code: ${FINAL_EXIT_CODE}" + echo "╠═════════════════════════════════════════════════════════════" + + local ok_count=0 fail_count=0 timeout_count=0 + + for entry in "${ACTION_LOG[@]}"; do + local status=$(echo "$entry" | cut -d'|' -f1) + local action=$(echo "$entry" | cut -d'|' -f2) + local details=$(echo "$entry" | cut -d'|' -f3-) + + case "$status" in + OK) ok_count=$((ok_count + 1)); echo "║ ✓ $action ($details)" ;; + FAILED) fail_count=$((fail_count + 1)); echo "║ ✗ $action ($details)" ;; + TIMEOUT) timeout_count=$((timeout_count + 1)); echo "║ ⏱ $action ($details)" ;; + esac + done + + echo "╠═════════════════════════════════════════════════════════════" + echo "║ OK: $ok_count | FAILED: $fail_count | TIMEOUT: $timeout_count" + echo "╚═════════════════════════════════════════════════════════════" + + exit ${FINAL_EXIT_CODE} + } + + trap execution_summary EXIT + + # ============================================================ + # RUN LOGIC + # ============================================================ + set -uo pipefail + + GIT_URL="$(params.git-url)" + REVISION="$(params.revision)" + PR_NAME="$(params.pipelinerun-name)" + PR_NS="$(params.pipelinerun-namespace)" + PIPELINE_STATUS="$(params.PIPELINE_AGGREGATE_STATUS)" + + # ── Read PipelineRun metadata ── + PR_JSON=$(kubectl get pipelinerun "$PR_NAME" -n "$PR_NS" -o json 2>/dev/null) + if [[ $? -ne 0 || -z "$PR_JSON" ]]; then + ACTION_LOG+=("FAILED|Read PipelineRun|exit=1|0s") + echo "Could not read PipelineRun $PR_NAME in $PR_NS (RBAC?)" + exit 0 + fi + ACTION_LOG+=("OK|Read PipelineRun|exit=0|0s") + + # ── Guard: only push events ── + EVENT_TYPE=$(echo "$PR_JSON" | jq -r \ + '.metadata.labels["pipelinesascode.tekton.dev/event-type"] // empty') + if [[ "$EVENT_TYPE" != "push" ]]; then + echo "Skipping: event-type is '${EVENT_TYPE:-unknown}', not 'push'" + ACTION_LOG+=("OK|Skip non-push event|exit=0|0s") + exit 0 + fi + + # ── Parse application label -> version + environment ── + APPLICATION=$(echo "$PR_JSON" | jq -r \ + '.metadata.labels["appstudio.openshift.io/application"] // empty') + if [[ -z "$APPLICATION" ]]; then + ACTION_LOG+=("FAILED|Parse application label|exit=1|0s") + echo "Missing appstudio.openshift.io/application label" + exit 0 + fi + + APP_SUFFIX="${APPLICATION#cnv-fbc-}" + if [[ "$APP_SUFFIX" == *-prod ]]; then + ENVIRONMENT="prod" + VERSION_RAW="${APP_SUFFIX%-prod}" + else + ENVIRONMENT="stage" + VERSION_RAW="$APP_SUFFIX" + fi + VERSION="${VERSION_RAW//-/.}" + ACTION_LOG+=("OK|Parse labels: version=$VERSION env=$ENVIRONMENT|exit=0|0s") + + echo "┌─────────────────────────────────────" + echo "│ FBC Build Status Report" + echo "├─────────────────────────────────────" + echo "│ Version: $VERSION" + echo "│ Environment: $ENVIRONMENT" + echo "│ Status: $PIPELINE_STATUS" + echo "│ Revision: ${REVISION:0:8}" + echo "└─────────────────────────────────────" + + # ── Fetch commit message from GitHub API ── + REPO_PATH=$(echo "$GIT_URL" | sed -n 's|.*github\.com[:/]\(.*\)\.git$|\1|p; s|.*github\.com[:/]\(.*\)$|\1|p') + if [[ -z "$REPO_PATH" ]]; then + ACTION_LOG+=("FAILED|Parse GitHub repo from git-url|exit=1|0s") + echo "Could not parse GitHub repo from: $GIT_URL" + exit 0 + fi + + COMMIT_JSON=$(curl -sf --max-time 30 \ + "https://api.github.com/repos/${REPO_PATH}/commits/${REVISION}" 2>/dev/null) + if [[ $? -ne 0 || -z "$COMMIT_JSON" ]]; then + ACTION_LOG+=("FAILED|Fetch commit message|exit=1|0s") + echo "GitHub API failed for ${REVISION:0:8} — skipping" + exit 0 + fi + COMMIT_MSG=$(echo "$COMMIT_JSON" | jq -r '.commit.message' | head -1) + ACTION_LOG+=("OK|Fetch commit message|exit=0|0s") + + # ── Extract BundleID and channel ── + BUNDLE_ID=$(echo "$COMMIT_MSG" | sed -n 's/.*hco-bundle-registry:\([^ ]*\).*/\1/p') + CHANNEL=$(echo "$COMMIT_MSG" | sed -n 's/.*on \(.*\) channel/\1/p') + + if [[ -z "$BUNDLE_ID" ]]; then + echo "Not a bundle update commit, skipping" + echo "Commit: $COMMIT_MSG" + ACTION_LOG+=("OK|Skip non-bundle commit|exit=0|0s") + exit 0 + fi + ACTION_LOG+=("OK|Extract BundleID=$BUNDLE_ID channel=${CHANNEL:-unknown}|exit=0|0s") + + # ── Validate secret ── + if [[ -z "${SMARTSHEET_TOKEN:-}" || -z "${SHEET_ID:-}" ]]; then + ACTION_LOG+=("FAILED|Validate smartsheets secret|exit=1|0s") + echo "smartsheets secret not configured (missing token or SheetId)" + exit 0 + fi + ACTION_LOG+=("OK|Validate smartsheets secret|exit=0|0s") + + # ── Smartsheet API with retry + exponential backoff ── + smartsheet_api_call() { + local METHOD="$1" ENDPOINT="$2" DATA="${3:-}" + local MAX_RETRIES=3 RETRY_DELAY=2 + + for ((i=1; i<=MAX_RETRIES; i++)); do + local CURL_ARGS=(-s -w "\n%{http_code}" --max-time 30 -X "$METHOD" + "https://api.smartsheet.com/2.0${ENDPOINT}" + -H "Authorization: Bearer ${SMARTSHEET_TOKEN}" + -H "Content-Type: application/json") + [[ -n "$DATA" ]] && CURL_ARGS+=(-d "$DATA") + + RESPONSE=$(curl "${CURL_ARGS[@]}" 2>/dev/null) + HTTP_CODE=$(echo "$RESPONSE" | tail -1) + BODY=$(echo "$RESPONSE" | sed '$d') + + case "$HTTP_CODE" in + 200|201) echo "$BODY"; return 0 ;; + 429) + echo "WARN: Rate limited, waiting ${RETRY_DELAY}s (attempt $i/$MAX_RETRIES)" >&2 + sleep "$RETRY_DELAY"; RETRY_DELAY=$((RETRY_DELAY * 2)) ;; + 401|403) + echo "ERROR: Auth failed (HTTP $HTTP_CODE)" >&2; return 1 ;; + *) + echo "WARN: API error $HTTP_CODE (attempt $i/$MAX_RETRIES)" >&2 + sleep "$RETRY_DELAY"; RETRY_DELAY=$((RETRY_DELAY * 2)) ;; + esac + done + echo "ERROR: Max retries exceeded" >&2; return 1 + } + + # ── Discover column IDs ── + echo "Discovering Smartsheet columns..." + COLUMNS_JSON=$(smartsheet_api_call "GET" "/sheets/${SHEET_ID}/columns" "") + if [[ $? -ne 0 || -z "$COLUMNS_JSON" ]]; then + ACTION_LOG+=("FAILED|Discover columns|exit=1|0s") + echo "Column discovery failed" + exit 0 + fi + + col_id() { echo "$COLUMNS_JSON" | jq -r --arg t "$1" '.data[] | select(.title==$t) | .id'; } + + COL_NAME=$(col_id "Name") + COL_BUNDLEID=$(col_id "BundleID") + COL_FBC_STAGE=$(col_id "FBC Stage") + COL_FBC_STAGE_RUN=$(col_id "FBC Stage Run") + COL_FBC_STAGE_CHANNEL=$(col_id "FBC Stage Channel") + COL_FBC_PROD=$(col_id "FBC Prod") + COL_FBC_PROD_RUN=$(col_id "FBC Prod Run") + COL_FBC_PROD_CHANNEL=$(col_id "FBC Prod Channel") + + if [[ -z "$COL_NAME" || "$COL_NAME" == "null" ]]; then + ACTION_LOG+=("FAILED|Validate columns|exit=1|0s") + echo "Primary column 'Name' not found" + exit 0 + fi + if [[ -z "$COL_BUNDLEID" || "$COL_BUNDLEID" == "null" ]]; then + ACTION_LOG+=("FAILED|Validate columns|exit=1|0s") + echo "Column 'BundleID' not found" + exit 0 + fi + ACTION_LOG+=("OK|Discover columns|exit=0|0s") + + # ── Select target columns based on environment ── + if [[ "$ENVIRONMENT" == "prod" ]]; then + COL_STATUS="$COL_FBC_PROD" + COL_RUN="$COL_FBC_PROD_RUN" + COL_CHANNEL="$COL_FBC_PROD_CHANNEL" + else + COL_STATUS="$COL_FBC_STAGE" + COL_RUN="$COL_FBC_STAGE_RUN" + COL_CHANNEL="$COL_FBC_STAGE_CHANNEL" + fi + + if [[ -z "$COL_STATUS" || "$COL_STATUS" == "null" ]]; then + ACTION_LOG+=("FAILED|Validate FBC columns|exit=1|0s") + echo "FBC columns not found — add them to the Smartsheet first" + exit 0 + fi + ACTION_LOG+=("OK|Select ${ENVIRONMENT} columns|exit=0|0s") + + # ── Fetch sheet data and find rows ── + SHEET_DATA=$(smartsheet_api_call "GET" "/sheets/${SHEET_ID}" "") + if [[ $? -ne 0 || -z "$SHEET_DATA" ]]; then + ACTION_LOG+=("FAILED|Fetch sheet data|exit=1|0s") + echo "Failed to fetch sheet data" + exit 0 + fi + ACTION_LOG+=("OK|Fetch sheet data|exit=0|0s") + + # L0: version row + VERSION_ROW_ID=$(echo "$SHEET_DATA" | jq -r --arg v "$VERSION" --argjson c "$COL_NAME" \ + '[.rows[]? | select(.parentId == null) | + select(.cells[]? | select(.columnId == $c and .value == $v))] | first | .id // empty') + + if [[ -z "$VERSION_ROW_ID" || "$VERSION_ROW_ID" == "null" ]]; then + ACTION_LOG+=("FAILED|Find L0 version row|exit=1|0s") + echo "Version row '$VERSION' not found" + exit 0 + fi + echo "Found L0 version row: $VERSION_ROW_ID" + + # L1: hco-bundle-registry application row + APP_ROW_ID=$(echo "$SHEET_DATA" | jq -r \ + --arg app "hco-bundle-registry" --argjson c "$COL_NAME" --argjson pid "$VERSION_ROW_ID" \ + '[.rows[]? | select(.parentId == $pid) | + select(.cells[]? | select(.columnId == $c and .value == $app))] | first | .id // empty') + + if [[ -z "$APP_ROW_ID" || "$APP_ROW_ID" == "null" ]]; then + ACTION_LOG+=("FAILED|Find L1 hco-bundle-registry row|exit=1|0s") + echo "hco-bundle-registry row not found under '$VERSION'" + exit 0 + fi + echo "Found L1 application row: $APP_ROW_ID" + ACTION_LOG+=("OK|Find L0=$VERSION_ROW_ID L1=$APP_ROW_ID|exit=0|0s") + + # L2: match by BundleID (last match for duplicates) + COMPONENT_ROW_ID=$(echo "$SHEET_DATA" | jq -r \ + --arg bid "$BUNDLE_ID" --argjson cb "$COL_BUNDLEID" --argjson pid "$APP_ROW_ID" \ + '[.rows[]? | select(.parentId == $pid) | + select(.cells[]? | select(.columnId == $cb and .value == $bid))] | last | .id // empty') + + if [[ -z "$COMPONENT_ROW_ID" || "$COMPONENT_ROW_ID" == "null" ]]; then + echo "WARN: No row with BundleID '$BUNDLE_ID' — falling back to latest L2 child" + COMPONENT_ROW_ID=$(echo "$SHEET_DATA" | jq -r --argjson pid "$APP_ROW_ID" \ + '[.rows[]? | select(.parentId == $pid)] | last | .id // empty') + if [[ -z "$COMPONENT_ROW_ID" || "$COMPONENT_ROW_ID" == "null" ]]; then + ACTION_LOG+=("FAILED|Find L2 component row|exit=1|0s") + echo "No L2 rows under hco-bundle-registry for '$VERSION'" + exit 0 + fi + echo "Using fallback L2 row: $COMPONENT_ROW_ID" + else + echo "Found L2 row by BundleID: $COMPONENT_ROW_ID" + fi + ACTION_LOG+=("OK|Find L2 row=$COMPONENT_ROW_ID|exit=0|0s") + + # ── Map status ── + case "$PIPELINE_STATUS" in + "Succeeded"|"Completed") DISPLAY_STATUS="Succeeded" ;; + "Failed") DISPLAY_STATUS="Failed" ;; + *) DISPLAY_STATUS="$PIPELINE_STATUS" ;; + esac + + # ── Build cell update payload ── + CELLS=$(jq -n \ + --argjson cs "$COL_STATUS" --arg status "$DISPLAY_STATUS" \ + --argjson cr "$COL_RUN" --arg run "$PR_NAME" \ + '[{columnId: $cs, value: $status}, {columnId: $cr, value: $run}]') + + if [[ -n "$COL_CHANNEL" && "$COL_CHANNEL" != "null" && -n "$CHANNEL" ]]; then + CELLS=$(echo "$CELLS" | jq --argjson cc "$COL_CHANNEL" --arg ch "$CHANNEL" \ + '. + [{columnId: $cc, value: $ch}]') + fi + + UPDATE_DATA=$(jq -n --argjson rid "$COMPONENT_ROW_ID" --argjson cells "$CELLS" \ + '[{id: $rid, cells: $cells}]') + + # ── Update row ── + smartsheet_api_call "PUT" "/sheets/${SHEET_ID}/rows" "$UPDATE_DATA" >/dev/null + if [[ $? -ne 0 ]]; then + ACTION_LOG+=("FAILED|Update Smartsheet row|exit=1|0s") + echo "Failed to update row $COMPONENT_ROW_ID" + exit 0 + fi + ACTION_LOG+=("OK|Update Smartsheet row|exit=0|0s") + + echo "" + echo "╔═════════════════════════════════════" + echo "║ FBC build status reported" + echo "║ Version: $VERSION" + echo "║ Environment: $ENVIRONMENT" + echo "║ BundleID: $BUNDLE_ID" + echo "║ Channel: ${CHANNEL:-unknown}" + echo "║ Status: $DISPLAY_STATUS" + echo "║ PipelineRun: $PR_NAME" + echo "╚═════════════════════════════════════" From 7c0b1a17d92af85bb3c234a5cf33027cb46c344c Mon Sep 17 00:00:00 2001 From: Axuba Date: Mon, 27 Apr 2026 17:33:25 +0200 Subject: [PATCH 83/88] Update if case image to handle v4.12 images --- pipelines/update-bundle.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index bb6c9b6..bcdfee2 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -291,7 +291,7 @@ spec: image_name=$(echo "$image_name_sha" | cut -d'@' -f1) # Virt-platform-autopilot should also be in the core-params - if [[ "$image_name" == *"-operator-rhel"* || "$image_name" == *"virt-platform-autopilot"* ]]; then + if [[ "$image_name" == *"-operator"* || "$image_name" == *"virt-platform-autopilot"* ]]; then json_file="components/hco-bundle-registry/core-params.json" else json_file="components/hco-bundle-registry/extra-params.json" From 002f70cf7e0d27181f5d05ca59069402b0e1c70c Mon Sep 17 00:00:00 2001 From: Axuba Date: Tue, 28 Apr 2026 10:43:52 +0200 Subject: [PATCH 84/88] Sort parameter json for clarity --- pipelines/update-bundle.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index bcdfee2..072986b 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -296,7 +296,7 @@ spec: else json_file="components/hco-bundle-registry/extra-params.json" fi - jq ".\"${image_name}-image\" = \"${image_name_sha}\"" "$json_file" > "${json_file}.tmp" && mv "${json_file}.tmp" "$json_file" + jq -S ".\"${image_name}-image\" = \"${image_name_sha}\"" "$json_file" > "${json_file}.tmp" && mv "${json_file}.tmp" "$json_file" done touch ${snapshots_file} From 30b9fe667d7304c8cca28bdc07d5686dc7a19fe5 Mon Sep 17 00:00:00 2001 From: Axuba Date: Tue, 28 Apr 2026 12:48:15 +0200 Subject: [PATCH 85/88] Do not add test images to core params --- pipelines/update-bundle.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 072986b..1792e5f 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -291,7 +291,7 @@ spec: image_name=$(echo "$image_name_sha" | cut -d'@' -f1) # Virt-platform-autopilot should also be in the core-params - if [[ "$image_name" == *"-operator"* || "$image_name" == *"virt-platform-autopilot"* ]]; then + if [[ "$image_name" == *"-operator"* || "$image_name" == *"virt-platform-autopilot"* || "$image_name" != *"-test-"* ]]; then json_file="components/hco-bundle-registry/core-params.json" else json_file="components/hco-bundle-registry/extra-params.json" From cf993acd44c94908b624bbbe90841915f50e90fd Mon Sep 17 00:00:00 2001 From: Axuba Date: Wed, 29 Apr 2026 14:26:54 +0200 Subject: [PATCH 86/88] Fix wrong if clause --- pipelines/update-bundle.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 1792e5f..28470a0 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -291,7 +291,7 @@ spec: image_name=$(echo "$image_name_sha" | cut -d'@' -f1) # Virt-platform-autopilot should also be in the core-params - if [[ "$image_name" == *"-operator"* || "$image_name" == *"virt-platform-autopilot"* || "$image_name" != *"-test-"* ]]; then + if [[ ("$image_name" == *"-operator"* || "$image_name" == *"virt-platform-autopilot"*) && "$image_name" != *"-test-"* ]]; then json_file="components/hco-bundle-registry/core-params.json" else json_file="components/hco-bundle-registry/extra-params.json" From 620a69853b3d38169004bee849f5386420e30e2b Mon Sep 17 00:00:00 2001 From: Axuba Date: Thu, 16 Jul 2026 17:44:27 +0200 Subject: [PATCH 87/88] Bump tag --- fbc/fbc-post-release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fbc/fbc-post-release.yaml b/fbc/fbc-post-release.yaml index 39fa2f7..1659e2c 100644 --- a/fbc/fbc-post-release.yaml +++ b/fbc/fbc-post-release.yaml @@ -44,7 +44,7 @@ spec: description: Full bundle version from updated_image.yaml steps: - name: get-info - image: quay.io/konflux-ci/release-service-utils:0a58b6a6b562879e89395636d97931f2dcbb494c + image: quay.io/konflux-ci/release-service-utils:105474114b10c0bd52eda96bc67490447131b784 envFrom: - secretRef: name: cnv-ci-release-token From 4f1cdca7682dbb7786743c1a8aa0dfa7c1cbad54 Mon Sep 17 00:00:00 2001 From: Albert Jubany Juarez Date: Mon, 27 Jul 2026 14:58:46 +0200 Subject: [PATCH 88/88] VMER-1129: Do not fail if commits are not consistent Signed-off-by: Albert Jubany Juarez --- pipelines/update-bundle.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pipelines/update-bundle.yaml b/pipelines/update-bundle.yaml index 28470a0..eaa84d8 100644 --- a/pipelines/update-bundle.yaml +++ b/pipelines/update-bundle.yaml @@ -264,11 +264,11 @@ spec: echo "│ Unique revisions:" jq -r '[.spec.components[].source.git.revision] | unique | .[] | "│ \(.)"' /tmp/snapshot.json echo "├─────────────────────────────────────────────────────────────" - echo "│ STATUS: FAILED (exit: 1, duration: 0s)" + echo "│ STATUS: WARN (exit: 0, duration: 0s)" echo "└─────────────────────────────────────────────────────────────" - ACTION_LOG+=("FAILED|Validate commit consistency|exit=1|0s") - FINAL_EXIT_CODE=1 - exit 1 + ACTION_LOG+=("WARN|Validate commit consistency|exit=0|0s") + FINAL_EXIT_CODE=0 + exit 0 fi rm -f /tmp/snapshot.json