Skip to content

Commit b36f2c1

Browse files
authored
fix: clean up untagged ECR images after overwrite_only_existing mirror (#245)
* Delete previous ECR digest after overwrite_only_existing push When overwriting an existing tag, ECR leaves the old manifest untagged. Remove it with batch-delete-image so hourly mirrors do not accumulate storage. * refactor: simplify mirror_to_ecr bash decision logic Collapse IMAGE_EXISTS/SHOULD_MIRROR into direct conditions without changing mirror, skip, fail, or digest-delete behavior. * fix: skip ECR digest deletion when mirror content is unchanged After push, compare the new image digest with the pre-push digest and only batch-delete the old digest when they differ, avoiding removal of the image that still carries the tag. * fix: delete all untagged ECR images after overwrite Replace digest-targeted deletion with list-images tagStatus=UNTAGGED cleanup so shared-tag digests are never removed unintentionally. * fix: quote ECR describe-images variables in mirror_to_ecr
1 parent 8206523 commit b36f2c1

1 file changed

Lines changed: 29 additions & 21 deletions

File tree

src/jobs/mirror_to_ecr.yml

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ parameters:
2020
type: boolean
2121
default: false
2222
overwrite_only_existing:
23-
description: If true then overwrite the image only when the target tag already exists in ECR. The job fails if the tag is missing.
23+
description: If true then overwrite the image only when the target tag already exists in ECR. The job fails if the tag is missing. After overwrite, untagged images in the repository are deleted from ECR.
2424
type: boolean
2525
default: false
2626
aws_profile:
@@ -45,47 +45,55 @@ steps:
4545
cmd_name: Mirroring image to ECR repository
4646
deploy: true
4747
cmd: |
48-
echo "Loging in to Dockerhub..."
48+
echo "Logging in to Dockerhub..."
4949
echo $DOCKER_PASS | docker login -u "$DOCKER_USER" --password-stdin
5050
5151
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
5252
export ECR_URL=${ACCOUNT_ID}.dkr.ecr.<< parameters.region >>.amazonaws.com
5353
export ECR_PASSWORD=$(aws ecr get-login-password --region << parameters.region >>)
54-
echo "Loging in to ECR: ${ECR_URL}"
54+
echo "Logging in to ECR: ${ECR_URL}"
5555
echo ${ECR_PASSWORD} | docker login -u AWS --password-stdin ${ECR_URL}
5656
5757
SRC_NAME="<< parameters.source_name >>"
5858
SRC_TAG="<< parameters.source_tag >>"
5959
SRC="${SRC_NAME}:${SRC_TAG}"
6060
6161
MIRROR_NAME="<< parameters.mirror_name >>"
62-
if [[ -z ${MIRROR_NAME} ]] ; then
63-
MIRROR_NAME="${SRC_NAME}"
64-
fi
65-
62+
MIRROR_NAME="${MIRROR_NAME:-${SRC_NAME}}"
6663
MIRROR_TAG="<< parameters.mirror_tag >>"
67-
if [[ -z ${MIRROR_TAG} ]] ; then
68-
MIRROR_TAG="${SRC_TAG}"
69-
fi
64+
MIRROR_TAG="${MIRROR_TAG:-${SRC_TAG}}"
7065
MIRROR="${MIRROR_NAME}:${MIRROR_TAG}"
7166
7267
echo "Mirroring ${SRC} to ${ECR_URL}/${MIRROR}..."
73-
REPO_DATA=$(aws ecr describe-images --repository-name=${MIRROR_NAME} --image-ids=imageTag=${MIRROR_TAG} ||: )
74-
SHOULD_MIRROR=false
75-
if [[ -z $REPO_DATA ]] ; then
76-
if << parameters.overwrite_only_existing >> ; then
77-
echo "Mirror target ${MIRROR} does not exist in ECR and overwrite_only_existing is enabled."
78-
exit 1
79-
fi
80-
SHOULD_MIRROR=true
81-
elif << parameters.force >> || << parameters.overwrite_only_existing >> ; then
82-
SHOULD_MIRROR=true
68+
OLD_IMAGE_DIGEST=$(aws ecr describe-images --repository-name="${MIRROR_NAME}" --image-ids=imageTag="${MIRROR_TAG}" --query 'imageDetails[0].imageDigest' --output text 2>/dev/null || true)
69+
[[ -z "${OLD_IMAGE_DIGEST}" || "${OLD_IMAGE_DIGEST}" == "None" ]] && OLD_IMAGE_DIGEST=""
70+
71+
if << parameters.overwrite_only_existing >> && [[ -z "${OLD_IMAGE_DIGEST}" ]]; then
72+
echo "Mirror target ${MIRROR} does not exist in ECR and overwrite_only_existing is enabled."
73+
exit 1
8374
fi
8475
85-
if [[ "${SHOULD_MIRROR}" == "true" ]] ; then
76+
if [[ -z "${OLD_IMAGE_DIGEST}" ]] || << parameters.force >> || << parameters.overwrite_only_existing >>; then
8677
docker pull ${SRC}
8778
docker tag ${SRC} ${ECR_URL}/${MIRROR}
8879
docker push ${ECR_URL}/${MIRROR}
80+
if << parameters.overwrite_only_existing >>; then
81+
UNTAGGED_DIGESTS=$(aws ecr list-images \
82+
--repository-name="${MIRROR_NAME}" \
83+
--filter tagStatus=UNTAGGED \
84+
--query 'imageIds[*].imageDigest' \
85+
--output text 2>/dev/null || true)
86+
if [[ -n "${UNTAGGED_DIGESTS}" && "${UNTAGGED_DIGESTS}" != "None" ]]; then
87+
echo "Deleting untagged images from ${MIRROR_NAME}..."
88+
IMAGE_IDS=()
89+
for digest in ${UNTAGGED_DIGESTS}; do
90+
IMAGE_IDS+=("imageDigest=${digest}")
91+
done
92+
aws ecr batch-delete-image --repository-name="${MIRROR_NAME}" --image-ids "${IMAGE_IDS[@]}"
93+
else
94+
echo "No untagged images to delete."
95+
fi
96+
fi
8997
else
9098
echo "${MIRROR} image is already in ECR"
9199
fi

0 commit comments

Comments
 (0)