1616 # Worst-case wall time per attempt is HEALTH_CHECK_INTERVAL plus the curl --max-time below
1717 # (10s), so the defaults give a ~10 minute window (24 × (15 + 10) = 600s) — enough for
1818 # most Rails cold boots (asset precompile + db:migrate + workload readiness).
19- HEALTH_CHECK_RETRIES : 24
20- HEALTH_CHECK_INTERVAL : 15
19+ HEALTH_CHECK_RETRIES : ${{ vars.HEALTH_CHECK_RETRIES || '24' }}
20+ HEALTH_CHECK_INTERVAL : ${{ vars.HEALTH_CHECK_INTERVAL || '15' }}
2121 # Space-separated list of HTTP statuses considered healthy. The default accepts 301/302
2222 # because `curl` is invoked without `-L`, so a root `/` that redirects to a login page
2323 # (common for Rails apps that auth-gate `/`) would otherwise be reported as unhealthy
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- ROLLBACK_READINESS_RETRIES : 24
35- ROLLBACK_READINESS_INTERVAL : 15
34+ ROLLBACK_READINESS_RETRIES : ${{ vars.ROLLBACK_READINESS_RETRIES || '24' }}
35+ ROLLBACK_READINESS_INTERVAL : ${{ vars.ROLLBACK_READINESS_INTERVAL || '15' }}
3636
3737concurrency :
3838 # Single global group: only one production promotion may run at a time across the
@@ -129,6 +129,7 @@ jobs:
129129 working_directory : .cpflow
130130 cpln_cli_version : ${{ vars.CPLN_CLI_VERSION }}
131131 cpflow_version : ${{ vars.CPFLOW_VERSION }}
132+ # The setup action validates CPFLOW_VERSION against this full workflow ref.
132133 control_plane_flow_ref : shakacode/control-plane-flow/.github/workflows/cpflow-promote-staging-to-production.yml@v5.0.4
133134
134135 # Runs after Setup production environment so the pinned Ruby (>= 3.1) is on PATH.
@@ -142,11 +143,12 @@ jobs:
142143 run : |
143144 set -euo pipefail
144145
145- ruby - "${PRODUCTION_APP_NAME}" "${PRIMARY_WORKLOAD}" >> "$ GITHUB_OUTPUT" <<'RUBY'
146+ ruby - "${PRODUCTION_APP_NAME}" "${PRIMARY_WORKLOAD}" "${ GITHUB_OUTPUT} " <<'RUBY'
146147 require "yaml"
147148
148149 app = ARGV.fetch(0)
149150 requested_primary = ARGV.fetch(1, "").to_s.strip
151+ output_path = ARGV.fetch(2)
150152 data = YAML.safe_load(File.read(".controlplane/controlplane.yml"), aliases: true)
151153 apps = data["apps"] || {}
152154 app_config = apps[app]
@@ -167,19 +169,21 @@ jobs:
167169 elsif workloads.include?("rails")
168170 "rails"
169171 else
170- warn "::error::PRIMARY_WORKLOAD is not configured and app '#{app}' has multiple workloads: #{workloads.join(', ')}."
172+ puts "::error::PRIMARY_WORKLOAD is not configured and app '#{app}' has multiple workloads: #{workloads.join(', ')}."
171173 warn " Set the PRIMARY_WORKLOAD repository variable to one of these workloads."
172174 exit 1
173175 end
174176 elsif workloads.include?(requested_primary)
175177 requested_primary
176178 else
177- warn "::error::PRIMARY_WORKLOAD '#{requested_primary}' is not one of: #{workloads.join(', ')}."
179+ puts "::error::PRIMARY_WORKLOAD '#{requested_primary}' is not one of: #{workloads.join(', ')}."
178180 exit 1
179181 end
180182
181- puts "names=#{workloads.join(',')}"
182- puts "primary=#{primary}"
183+ File.open(output_path, "a") do |output|
184+ output.puts "names=#{workloads.join(',')}"
185+ output.puts "primary=#{primary}"
186+ end
183187 RUBY
184188
185189 - name : Detect release phase support
@@ -245,7 +249,7 @@ jobs:
245249 [[ -n "${workload_name}" ]] || continue
246250
247251 workload_json="$(cpln workload get "${workload_name}" --gvc "${PRODUCTION_APP_NAME}" --org "${CPLN_ORG_PRODUCTION}" -o json)"
248- workload_image="$(echo "${workload_json}" | jq -r '.spec.containers[0].image')"
252+ workload_image="$(echo "${workload_json}" | jq -r '.spec.containers[0].image // empty ')"
249253 workload_containers="$(echo "${workload_json}" | jq -c '.spec.containers | map({name, image})')"
250254 workload_version="$(echo "${workload_json}" | jq -r '.version')"
251255
@@ -377,6 +381,7 @@ jobs:
377381 run : |
378382 # Best-effort rollback: try every workload, aggregate failures, exit non-zero at the end
379383 # if any failed. A single cpln hiccup shouldn't leave other workloads mid-promotion.
384+ # Keep -e disabled here so rollback can aggregate failures across workloads.
380385 set -uo pipefail
381386
382387 rollback_failures=0
0 commit comments