Skip to content

Commit

Permalink
feat(RELEASE-1245): make publish index image task idempotent
Browse files Browse the repository at this point in the history
Signed-off-by: Happy Bhati <[email protected]>
  • Loading branch information
happybhati committed Feb 4, 2025
1 parent d6c5232 commit e7f5a58
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 17 deletions.
3 changes: 3 additions & 0 deletions tasks/internal/publish-index-image-task/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ Tekton task to publish a built FBC index image using skopeo
| retries | Number of skopeo retries | Yes | 0 |
| publishingCredentials | The credentials used to access the registries | No | - |
| requestUpdateTimeout | Max seconds waiting for the status update | Yes | 360 |

## Changes in 0.2.0
* Make publish index image task idempotent
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ kind: Task
metadata:
name: publish-index-image-task
labels:
app.kubernetes.io/version: "0.1.1"
app.kubernetes.io/version: "0.2.1"
annotations:
tekton.dev/pipelines.minVersion: "0.12.1"
tekton.dev/tags: release
Expand Down Expand Up @@ -49,24 +49,53 @@ spec:
quay.io/konflux-ci/release-service-utils:e633d51cd41d73e4b3310face21bb980af7a662f
script: |
#!/usr/bin/env bash
set -euo pipefail
PATH=/bin:/usr/bin:/usr/local/bin
export PATH
# do not authenticate if the source is redhat's "registry-proxy" which is unauthenticated.
SOURCE_AUTH_ARGS=()
# Do not authenticate if the source is Red Hat's "registry-proxy" which is unauthenticated.
if [[ ! "$(params.sourceIndex)" =~ ^registry-proxy(\-stage)?.engineering.redhat.com ]]; then
AUTH_PARAM=("--src-creds" "${SOURCE_INDEX_CREDENTIAL}")
SOURCE_AUTH_ARGS=("--src-creds" "${SOURCE_INDEX_CREDENTIAL}")
fi
TARGET_AUTH_ARGS=("--dest-creds" "${TARGET_INDEX_CREDENTIAL}")
# Get source image digest
echo "Getting source image digest: $(params.sourceIndex)"
if ! SOURCE_DIGEST=$(skopeo inspect --tls-verify=false "${SOURCE_AUTH_ARGS[@]}" "docker://$(params.sourceIndex)" --format '{{.Digest}}'); then

Check failure on line 67 in tasks/internal/publish-index-image-task/publish-index-image-task.yaml

View workflow job for this annotation

GitHub Actions / yamllint

line too long
echo "Error: Failed to fetch source image digest for $(params.sourceIndex)" >&2
echo "Failed to get source image digest" | tee "$(results.requestMessage.path)"
exit 1
fi
# Get target image digest (handle cases where it doesn't exist)
echo "Getting target image digest: $(params.targetIndex)"
if TARGET_DIGEST=$(skopeo inspect --tls-verify=false "${TARGET_AUTH_ARGS[@]}" "docker://$(params.targetIndex)" --format '{{.Digest}}'); then

Check failure on line 75 in tasks/internal/publish-index-image-task/publish-index-image-task.yaml

View workflow job for this annotation

GitHub Actions / yamllint

line too long
echo "Target image exists."
if [ "$SOURCE_DIGEST" == "$TARGET_DIGEST" ]; then
echo "Image already exists in target registry with the same digest. Skipping copy." | tee "$(results.requestMessage.path)"

Check failure on line 78 in tasks/internal/publish-index-image-task/publish-index-image-task.yaml

View workflow job for this annotation

GitHub Actions / yamllint

line too long
exit 0
else
echo "Image exists in target registry but digests do not match. Proceeding to copy the image."
fi
else
echo "Target image does not exist. Proceeding to copy the image."
fi
# Proceed with copying the image
echo "Copying image from $(params.sourceIndex) to $(params.targetIndex)"
(skopeo copy \
--all \
--preserve-digests \
--retry-times "$(params.retries)" \
--src-tls-verify=false "${AUTH_PARAM[@]}" \
--src-tls-verify=false "${SOURCE_AUTH_ARGS[@]}" \
"docker://$(params.sourceIndex)" \
--dest-creds "${TARGET_INDEX_CREDENTIAL}" \
"${TARGET_AUTH_ARGS[@]}" \
"docker://$(params.targetIndex)" && \
echo -n "Index Image Published successfully" || \
echo -n "Failed publishing Index Image" ) | tee "$(results.requestMessage.path)"
# trick to get the proper exit status
# Ensure the script exits with the correct status
grep "success" "$(results.requestMessage.path)" >/dev/null
31 changes: 20 additions & 11 deletions tasks/internal/publish-index-image-task/tests/mocks.sh
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
#!/usr/bin/env bash
set -x

# mocks to be injected into task step scripts

function skopeo() {
echo Mock skopeo called with: $* >&2
echo Mock skopeo called with: "$*" >&2

# Handle "skopeo inspect" for a failing case
if [[ "$*" == *"inspect --tls-verify=false docker://registry-proxy.engineering.redhat.com/fail --format '{{.Digest}}'"* ]]; then
echo "Mock failure: Image does not exist" >&2
return 1

if [[ "$*" == *"--src-tls-verify=false --src-creds source docker://quay.io/source"* ]]
then
# Handle "skopeo inspect" for a successful case
elif [[ "$*" == *"inspect --tls-verify=false docker://registry-proxy.engineering.redhat.com/foo --format '{{.Digest}}'"* ]]; then
echo "sha256:abcd1234"
return 0
elif [[ "$*" == *"--src-tls-verify=false docker://registry-proxy.engineering.redhat.com/foo"* ]]
then

# Handle "skopeo inspect" for target image check
elif [[ "$*" == *"inspect --tls-verify=false docker://quay.io/target --format '{{.Digest}}'"* ]]; then
echo "sha256:xyz9876"
return 0
elif [[ "$*" == *"--src-tls-verify=false docker://registry-proxy.engineering.redhat.com/fail"* ]]
then
return 1

# Handle "skopeo copy"
elif [[ "$*" == *"skopeo copy"* ]]; then
echo "Mock skopeo copy called with: $*"
return 0

else
echo Error: Unexpected call
echo "Error: Unexpected call"
exit 1
fi
}

0 comments on commit e7f5a58

Please sign in to comment.