Skip to content

Commit c45e3ac

Browse files
committed
Harden production promotion image copy
1 parent 86f315a commit c45e3ac

1 file changed

Lines changed: 28 additions & 9 deletions

File tree

.github/workflows/cpflow-promote-staging-to-production.yml

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ env:
3131
# expose a dedicated health endpoint (e.g. "200" for a plain /health, or "200 401 403"
3232
# for apps that auth-gate / without redirecting).
3333
HEALTH_CHECK_ACCEPTED_STATUSES: ${{ vars.HEALTH_CHECK_ACCEPTED_STATUSES || '200 301 302' }}
34+
COPY_IMAGE_RETRIES: ${{ vars.COPY_IMAGE_RETRIES || '3' }}
35+
COPY_IMAGE_RETRY_INTERVAL: ${{ vars.COPY_IMAGE_RETRY_INTERVAL || '20' }}
3436
ROLLBACK_READINESS_RETRIES: ${{ vars.ROLLBACK_READINESS_RETRIES || '24' }}
3537
ROLLBACK_READINESS_INTERVAL: ${{ vars.ROLLBACK_READINESS_INTERVAL || '15' }}
3638

@@ -336,14 +338,36 @@ jobs:
336338
- name: Copy image from staging
337339
env:
338340
# Pass the upstream token via env rather than `-t` so it doesn't appear in /proc/<pid>/cmdline.
341+
CPLN_TOKEN_STAGING: ${{ secrets.CPLN_TOKEN_STAGING }}
339342
CPLN_UPSTREAM_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }}
340343
PRODUCTION_APP_NAME: ${{ vars.PRODUCTION_APP_NAME }}
344+
CPLN_ORG_STAGING: ${{ vars.CPLN_ORG_STAGING }}
341345
CPLN_ORG_PRODUCTION: ${{ vars.CPLN_ORG_PRODUCTION }}
342346
STAGING_IMAGE: ${{ steps.staging-image.outputs.image }}
343347
shell: bash
344348
run: |
345349
set -euo pipefail
346-
cpflow copy-image-from-upstream -a "${PRODUCTION_APP_NAME}" --org "${CPLN_ORG_PRODUCTION}" --image "${STAGING_IMAGE}"
350+
351+
CPLN_TOKEN="${CPLN_TOKEN_STAGING}" cpln image get "${STAGING_IMAGE}" --org "${CPLN_ORG_STAGING}" -o json >/dev/null
352+
353+
copy_status=1
354+
for attempt in $(seq 1 "${COPY_IMAGE_RETRIES}"); do
355+
if cpflow copy-image-from-upstream -a "${PRODUCTION_APP_NAME}" --org "${CPLN_ORG_PRODUCTION}" --image "${STAGING_IMAGE}"; then
356+
copy_status=0
357+
break
358+
fi
359+
360+
copy_status=$?
361+
if [[ "${attempt}" -lt "${COPY_IMAGE_RETRIES}" ]]; then
362+
echo "::warning::Image copy attempt ${attempt}/${COPY_IMAGE_RETRIES} failed with exit ${copy_status}; retrying in ${COPY_IMAGE_RETRY_INTERVAL}s."
363+
sleep "${COPY_IMAGE_RETRY_INTERVAL}"
364+
fi
365+
done
366+
367+
if [[ "${copy_status}" -ne 0 ]]; then
368+
echo "::error::Could not copy staging image '${STAGING_IMAGE}' from '${CPLN_ORG_STAGING}' to '${CPLN_ORG_PRODUCTION}' after ${COPY_IMAGE_RETRIES} attempt(s)."
369+
exit "${copy_status}"
370+
fi
347371
348372
- name: Deploy image to production
349373
env:
@@ -411,19 +435,14 @@ jobs:
411435
continue
412436
fi
413437
414-
if ! rollback_container_entries="$(
415-
jq -r \
416-
--argjson current_names "${current_names}" \
417-
'.[] as $container | ($current_names | index($container.name)) as $index | "\($index)\t\($container.image)"' \
418-
<<< "${previous_containers}"
419-
)"; then
438+
if ! rollback_container_entries="$(jq -r '.[] | "\(.name)\t\(.image)"' <<< "${previous_containers}")"; then
420439
echo "::warning::Could not build rollback image list for workload '${workload_name}'; skipping rollback for this workload." >&2
421440
rollback_failures=$((rollback_failures + 1))
422441
continue
423442
fi
424443
425-
while IFS=$'\t' read -r index image; do
426-
rollback_args+=(--set "spec.containers[${index}].image=${image}")
444+
while IFS=$'\t' read -r container_name image; do
445+
rollback_args+=(--set "spec.containers.${container_name}.image=${image}")
427446
done <<< "${rollback_container_entries}"
428447
429448
if ! cpln workload update "${workload_name}" \

0 commit comments

Comments
 (0)