ci: make deploy webhook curl robust and observable (#484)

## Problem

The deploy step intermittently fails on CI with only:

```
Response:
HTTP Status: 000
Deployment request failed with status 000
```

`000` means curl never completed a connection — the Coolify box (which
rebuilds the image from git on deploy) has its API unreachable while a
prior build runs. But the step gave no way to confirm that: `-s`
silenced curl's error message and `|| true` swallowed the exit code.

## Changes

- **Surface the real cause** — `-sS` plus `--write-out
%{exitcode}`/`%{errormsg}`/timing, so failures print the curl exit code
(7 refused, 28 timeout, …) and message instead of a blind `000`.
- **Robust parsing** — body/metadata split on an explicit
`===CURL_META===` marker instead of fragile `tail`/`sed` line counting.
- **No false timeouts** — `--max-time` raised 120→300s so a
slow-but-alive box doesn't abort mid-trigger and report a phantom `000`.
- **Wider retry window** — 10 attempts with backoff capped at 60s (~8
min) instead of 5 with a 240s dead sleep, to ride out a multi-minute
rebuild.
- **Fail fast on 4xx** — a bad token/uuid is not retryable, so don't
waste the window on it.

## Note

This makes the trigger robust and observable; the structural fix (let
Coolify pull the prebuilt ghcr image instead of rebuilding on the box)
is out of scope here.
This commit is contained in:
Víctor Falcón 2026-06-04 08:46:18 +02:00 committed by GitHub
parent 1cc10566a3
commit e3cbbb2e0d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 36 additions and 11 deletions

View File

@ -588,33 +588,58 @@ jobs:
- name: Trigger deployment
if: steps.deploy_guard.outputs.should_deploy == 'true'
run: |
max_attempts=5
# The Coolify box rebuilds the image from git on deploy, so its API
# (port 8000) can be unreachable for several minutes while a prior
# build runs. We just need the webhook to land once: retry on
# connection-level failures with a capped backoff over a wide window.
max_attempts=10
max_delay=60
attempt=1
# Separator we control, so curl's --write-out fields can never be
# confused with the response body.
marker="===CURL_META==="
while [ $attempt -le $max_attempts ]; do
echo "Attempt $attempt of $max_attempts..."
response=$(curl -s -w "\n%{http_code}" \
curl_exit=0
response=$(curl -sS \
-w "${marker}\nhttp_code=%{http_code}\ncurl_exit=%{exitcode}\nerrormsg=%{errormsg}\ntiming=DNS:%{time_namelookup}s Connect:%{time_connect}s Total:%{time_total}s Remote:%{remote_ip}:%{remote_port}" \
--connect-timeout 30 \
--max-time 120 \
--max-time 300 \
-H "Authorization: Bearer ${{ secrets.DEPLOYMENT_TOKEN }}" \
"http://147.93.126.54:8000/api/v1/deploy?uuid=ww00sswosco8w80k08c0occ8&force=false") || true
"http://147.93.126.54:8000/api/v1/deploy?uuid=ww00sswosco8w80k08c0occ8&force=false") || curl_exit=$?
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
body="${response%%${marker}*}"
meta="${response#*${marker}}"
http_code=$(echo "$meta" | sed -n 's/^http_code=//p')
curl_code=$(echo "$meta" | sed -n 's/^curl_exit=//p')
errormsg=$(echo "$meta" | sed -n 's/^errormsg=//p')
timing=$(echo "$meta" | sed -n 's/^timing=//p')
echo "Response: $body"
echo "HTTP Status: ${http_code:-timeout}"
echo "Response body: $body"
echo "HTTP Status: ${http_code:-none}"
echo "curl exit: ${curl_code:-$curl_exit}"
echo "curl error: ${errormsg:-none}"
echo "Timing: $timing"
if [ -n "$http_code" ] && [ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ]; then
if [ "${http_code:-0}" -ge 200 ] && [ "${http_code:-0}" -lt 300 ]; then
echo "Deployment triggered successfully!"
exit 0
fi
echo "Deployment request failed with status $http_code"
# 4xx are caller errors (bad token / uuid) — retrying won't help.
if [ "${http_code:-0}" -ge 400 ] && [ "${http_code:-0}" -lt 500 ]; then
echo "Got client error $http_code — not retryable. Failing fast."
exit 1
fi
echo "Deployment request failed (http=${http_code:-none} curl_exit=${curl_code:-$curl_exit}: ${errormsg:-none})"
if [ $attempt -lt $max_attempts ]; then
delay=$((30 * (2 ** (attempt - 1))))
delay=$((15 * attempt))
[ $delay -gt $max_delay ] && delay=$max_delay
echo "Retrying in ${delay}s..."
sleep $delay
fi