|
31 | 31 | # expose a dedicated health endpoint (e.g. "200" for a plain /health, or "200 401 403" |
32 | 32 | # for apps that auth-gate / without redirecting). |
33 | 33 | 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' }} |
34 | 36 | ROLLBACK_READINESS_RETRIES: ${{ vars.ROLLBACK_READINESS_RETRIES || '24' }} |
35 | 37 | ROLLBACK_READINESS_INTERVAL: ${{ vars.ROLLBACK_READINESS_INTERVAL || '15' }} |
36 | 38 |
|
@@ -336,14 +338,36 @@ jobs: |
336 | 338 | - name: Copy image from staging |
337 | 339 | env: |
338 | 340 | # 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 }} |
339 | 342 | CPLN_UPSTREAM_TOKEN: ${{ secrets.CPLN_TOKEN_STAGING }} |
340 | 343 | PRODUCTION_APP_NAME: ${{ vars.PRODUCTION_APP_NAME }} |
| 344 | + CPLN_ORG_STAGING: ${{ vars.CPLN_ORG_STAGING }} |
341 | 345 | CPLN_ORG_PRODUCTION: ${{ vars.CPLN_ORG_PRODUCTION }} |
342 | 346 | STAGING_IMAGE: ${{ steps.staging-image.outputs.image }} |
343 | 347 | shell: bash |
344 | 348 | run: | |
345 | 349 | 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 |
347 | 371 |
|
348 | 372 | - name: Deploy image to production |
349 | 373 | env: |
@@ -411,19 +435,14 @@ jobs: |
411 | 435 | continue |
412 | 436 | fi |
413 | 437 |
|
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 |
420 | 439 | echo "::warning::Could not build rollback image list for workload '${workload_name}'; skipping rollback for this workload." >&2 |
421 | 440 | rollback_failures=$((rollback_failures + 1)) |
422 | 441 | continue |
423 | 442 | fi |
424 | 443 |
|
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}") |
427 | 446 | done <<< "${rollback_container_entries}" |
428 | 447 |
|
429 | 448 | if ! cpln workload update "${workload_name}" \ |
|
0 commit comments