From dee732c3eb271694c914c2cf2c9036ec2b5f5b5a Mon Sep 17 00:00:00 2001 From: Leandro Mendes Date: Mon, 29 Jun 2026 11:51:28 +0200 Subject: [PATCH] fix(KONFLUX-14665): check also internalrequest status This PR adds a check of the internal-request status after the publish happened as in case of time-out, there will be no error to be caught, instead we will have a IR failed condition. Assisted-By: Claude Signed-off-by: Leandro Mendes --- .../publish-index-image.yaml | 13 +- .../publish-index-image/tests/mocks.sh | 46 +++++- .../test-publish-index-image-failure.yaml | 142 ++++++++++++++++++ 3 files changed, 198 insertions(+), 3 deletions(-) create mode 100644 tasks/managed/publish-index-image/tests/test-publish-index-image-failure.yaml diff --git a/tasks/managed/publish-index-image/publish-index-image.yaml b/tasks/managed/publish-index-image/publish-index-image.yaml index 56b0d650a7..27cd0272c9 100644 --- a/tasks/managed/publish-index-image/publish-index-image.yaml +++ b/tasks/managed/publish-index-image/publish-index-image.yaml @@ -197,7 +197,18 @@ spec: internalRequest=$(awk -F"'" '/created/ { print $2 }' "$IR_RESULT_FILE") echo "done (${internalRequest})" - results=$(kubectl get internalrequest "${internalRequest}" -o=jsonpath='{.status.results}') + # get the internal request status + internalRequestJson="$(kubectl get internalrequest "${internalRequest}" -o json | jq -c)" + + status="$(jq '.status.conditions[].status' <<< "$internalRequestJson")" + if [ "$status" = "False" ]; then + errorMessage="$(jq '.status.conditions[].message' <<< "$internalRequestJson")" + echo "ERROR: Publish to ${publishingImages[$x]} failed" + echo "errorMessage: $errorMessage" + exit 1 + fi + + results=$(jq '.status.results' <<< "$internalRequestJson") requestMessage=$(echo "${results}" | jq -r '.requestMessage // ""') if echo "${requestMessage}" | grep -qi "error"; then diff --git a/tasks/managed/publish-index-image/tests/mocks.sh b/tasks/managed/publish-index-image/tests/mocks.sh index 3cd718ac88..2842744e9a 100644 --- a/tasks/managed/publish-index-image/tests/mocks.sh +++ b/tasks/managed/publish-index-image/tests/mocks.sh @@ -15,9 +15,51 @@ function internal-request() { } function kubectl() { - if [[ "$*" == *"get internalrequest"*"jsonpath"*"status.results"* ]] + if [[ "$*" == *"get internalrequest"*"-o json"* ]] then - echo '{"requestMessage":"Index Image Published successfully"}' + # Check if this is the failure test case by looking for a marker file in dataDir + # The dataDir is mounted at /var/workdir/release by default + if [ -f /var/workdir/release/.test-failure-marker ]; then + echo '{ + "status": { + "conditions": [ + { + "type": "Succeeded", + "status": "False", + "reason": "Failed", + "message": "Failed to publish index image: permission denied to registry" + } + ], + "results": { + "requestMessage": "Error: Failed to push image" + } + } + }' + else + # Return successful status for normal tests + echo '{ + "status": { + "conditions": [ + { + "type": "Succeeded", + "status": "True", + "reason": "Succeeded", + "message": "" + } + ], + "results": { + "requestMessage": "Index Image Published successfully" + } + } + }' + fi + elif [[ "$*" == *"get internalrequest"*"jsonpath"*"status.results"* ]] + then + if [ -f /var/workdir/release/.test-failure-marker ]; then + echo '{"requestMessage":"Error: Failed to push image"}' + else + echo '{"requestMessage":"Index Image Published successfully"}' + fi else /usr/bin/kubectl $* fi diff --git a/tasks/managed/publish-index-image/tests/test-publish-index-image-failure.yaml b/tasks/managed/publish-index-image/tests/test-publish-index-image-failure.yaml new file mode 100644 index 0000000000..73bab8a096 --- /dev/null +++ b/tasks/managed/publish-index-image/tests/test-publish-index-image-failure.yaml @@ -0,0 +1,142 @@ +--- +apiVersion: tekton.dev/v1 +kind: Pipeline +metadata: + name: test-publish-index-image-failure + annotations: + test/assert-task-failure: "run-task" +spec: + description: Test that publish-index-image task properly handles InternalRequest failures + params: + - name: ociStorage + description: The OCI repository where the Trusted Artifacts are stored. + type: string + - name: ociArtifactExpiresAfter + description: Expiration date for the trusted artifacts created in the + OCI repository. An empty string means the artifacts do not expire. + type: string + default: "1d" + - name: orasOptions + description: oras options to pass to Trusted Artifacts calls + type: string + default: "--insecure" + - name: trustedArtifactsDebug + description: Flag to enable debug logging in trusted artifacts. Set to a non-empty string to enable. + type: string + default: "" + - name: dataDir + description: The location where data will be stored + type: string + tasks: + - name: setup + taskSpec: + results: + - name: sourceDataArtifact + type: string + volumes: + - name: workdir + emptyDir: {} + stepTemplate: + volumeMounts: + - mountPath: /var/workdir + name: workdir + env: + - name: IMAGE_EXPIRES_AFTER + value: $(params.ociArtifactExpiresAfter) + - name: "ORAS_OPTIONS" + value: "$(params.orasOptions)" + - name: "DEBUG" + value: "$(params.trustedArtifactsDebug)" + steps: + - name: setup-values + image: quay.io/konflux-ci/release-service-utils@sha256:5546fa78d3c88d7b6a2e8cff8902f7757f00541d0bbaf113b9f293133894afa3 + script: | + #!/usr/bin/env sh + set -eux + + mkdir -p "$(params.dataDir)/$(context.pipelineRun.uid)" + + # Create marker file to trigger failure in mocks + touch "$(params.dataDir)/.test-failure-marker" + + cat > "$(params.dataDir)/$(context.pipelineRun.uid)/data.json" << EOF + { + "fbc": { + "publishingCredentials": "test-credentials" + } + } + EOF + cat > "$(params.dataDir)/internal-requests-results.json" << EOF + { + "index_image": { + "target_index": "quay.io/scoheb/fbc-target-index-testing:v4.12" + }, + "components": [ + { + "fbc_fragment": "registry.io/image0@sha256:0000", + "target_index": "quay.io/scoheb/fbc-target-index-testing:v4.12", + "target_index_with_timestamp": "quay.io/scoheb/fbc-target-index-testing:v4.12-1678118351", + "ocp_version": "v4.12", + "index_image": "redhat.com/rh-stage/iib:01", + "index_image_resolved": "redhat.com/rh-stage/iib@sha256:abcdefghijk", + "image_digests": [ + "quay.io/a", + "quay.io/b" + ], + "completion_time": "2023-03-06T16:39:11.314092Z", + "iibLog": "Dummy IIB Log" + } + ] + } + EOF + - name: create-trusted-artifact + ref: + name: create-trusted-artifact + params: + - name: ociStorage + value: $(params.ociStorage) + - name: workDir + value: $(params.dataDir) + - name: sourceDataArtifact + value: $(results.sourceDataArtifact.path) + - name: run-task + taskRef: + name: publish-index-image + params: + - name: internalRequestResultsFile + value: "internal-requests-results.json" + - name: buildTimestamp + value: 11111111111 + - name: retries + value: 2 + - name: pipelineRunUid + value: $(context.pipelineRun.uid) + - name: dataPath + value: $(context.pipelineRun.uid)/data.json + - name: ociStorage + value: $(params.ociStorage) + - name: orasOptions + value: $(params.orasOptions) + - name: sourceDataArtifact + value: "$(tasks.setup.results.sourceDataArtifact)=$(params.dataDir)" + - name: dataDir + value: $(params.dataDir) + - name: trustedArtifactsDebug + value: $(params.trustedArtifactsDebug) + - name: taskGitUrl + value: "http://localhost" + - name: taskGitRevision + value: "main" + runAfter: + - setup + finally: + - name: cleanup + taskSpec: + steps: + - name: delete-crs + image: quay.io/konflux-ci/release-service-utils@sha256:5546fa78d3c88d7b6a2e8cff8902f7757f00541d0bbaf113b9f293133894afa3 + script: | + #!/usr/bin/env bash + set -euxo pipefail + + kubectl delete internalrequests --all