feat: add debug information and response headers to Portainer stack deployment
All checks were successful
Build And Publish Production Image / Build And Publish Production Image (push) Successful in 7s

This commit is contained in:
2026-03-28 14:54:22 -03:00
parent af5def1e71
commit ff93afd075

View File

@@ -75,6 +75,8 @@ jobs:
') ')
echo "Loaded $(printf '%s' "${ENV_JSON}" | jq 'length') env entries from ENV_VARS" echo "Loaded $(printf '%s' "${ENV_JSON}" | jq 'length') env entries from ENV_VARS"
echo "ENV names preview:"
printf '%s' "${ENV_JSON}" | jq -r '.[0:10][]?.name' || true
echo "Portainer base URL: ${PORTAINER_BASE_URL}" echo "Portainer base URL: ${PORTAINER_BASE_URL}"
echo "Target stack: ${STACK_NAME}" echo "Target stack: ${STACK_NAME}"
echo "Endpoint id set: $([ -n "${PORTAINER_ENDPOINT_ID}" ] && echo yes || echo no)" echo "Endpoint id set: $([ -n "${PORTAINER_ENDPOINT_ID}" ] && echo yes || echo no)"
@@ -97,10 +99,12 @@ jobs:
fi fi
STACKS_BODY=$(mktemp) STACKS_BODY=$(mktemp)
STACKS_HEADERS=$(mktemp)
STACKS_ERR=$(mktemp) STACKS_ERR=$(mktemp)
STACKS_HTTP_CODE=$(curl -sS \ STACKS_HTTP_CODE=$(curl -sS \
--noproxy "*" \ --noproxy "*" \
-D "${STACKS_HEADERS}" \
-o "${STACKS_BODY}" \ -o "${STACKS_BODY}" \
-w "%{http_code}" \ -w "%{http_code}" \
"${ACTIVE_PORTAINER_BASE_URL}/api/stacks" \ "${ACTIVE_PORTAINER_BASE_URL}/api/stacks" \
@@ -110,11 +114,14 @@ jobs:
echo "GET /api/stacks curl exit: ${STACKS_CURL_EXIT}" echo "GET /api/stacks curl exit: ${STACKS_CURL_EXIT}"
echo "GET /api/stacks http code: ${STACKS_HTTP_CODE}" echo "GET /api/stacks http code: ${STACKS_HTTP_CODE}"
echo "GET /api/stacks headers:"
cat "${STACKS_HEADERS}" || true
if [ "${STACKS_CURL_EXIT}" -eq 6 ] && [ -n "${PORTAINER_IP:-}" ]; then if [ "${STACKS_CURL_EXIT}" -eq 6 ] && [ -n "${PORTAINER_IP:-}" ]; then
echo "Retrying stack list with IP fallback due to DNS failure" echo "Retrying stack list with IP fallback due to DNS failure"
STACKS_HTTP_CODE=$(curl -sS \ STACKS_HTTP_CODE=$(curl -sS \
--noproxy "*" \ --noproxy "*" \
-D "${STACKS_HEADERS}" \
-o "${STACKS_BODY}" \ -o "${STACKS_BODY}" \
-w "%{http_code}" \ -w "%{http_code}" \
"${PORTAINER_IP_BASE_URL}/api/stacks" \ "${PORTAINER_IP_BASE_URL}/api/stacks" \
@@ -143,20 +150,27 @@ jobs:
STACK_ID=$(jq -r --arg stack_name "${STACK_NAME}" '.[] | select(.Name == $stack_name) | .Id' "${STACKS_BODY}" | head -n 1) STACK_ID=$(jq -r --arg stack_name "${STACK_NAME}" '.[] | select(.Name == $stack_name) | .Id' "${STACKS_BODY}" | head -n 1)
APPLY_BODY=$(mktemp) APPLY_BODY=$(mktemp)
APPLY_HEADERS=$(mktemp)
APPLY_ERR=$(mktemp) APPLY_ERR=$(mktemp)
if [ -n "${STACK_ID}" ]; then if [ -n "${STACK_ID}" ]; then
echo "Updating existing stack id=${STACK_ID}" echo "Updating existing stack id=${STACK_ID}"
REQUEST_URL="${ACTIVE_PORTAINER_BASE_URL}/api/stacks/${STACK_ID}?endpointId=${PORTAINER_ENDPOINT_ID}"
PAYLOAD=$(jq -n \ PAYLOAD=$(jq -n \
--rawfile stack_file docker-compose.prod.yml \ --rawfile stack_file docker-compose.prod.yml \
--argjson env_vars "${ENV_JSON}" \ --argjson env_vars "${ENV_JSON}" \
'{StackFileContent: $stack_file, Env: $env_vars, Prune: false, PullImage: true}') '{StackFileContent: $stack_file, Env: $env_vars, Prune: false, PullImage: true}')
echo "Apply request URL: ${REQUEST_URL}"
echo "Apply payload summary:"
printf '%s' "${PAYLOAD}" | jq -r '{stackFileLength: (.StackFileContent | length), envCount: (.Env | length), prune: .Prune, pullImage: .PullImage}' || true
APPLY_HTTP_CODE=$(curl -sS -X PUT \ APPLY_HTTP_CODE=$(curl -sS -X PUT \
--noproxy "*" \ --noproxy "*" \
-D "${APPLY_HEADERS}" \
-o "${APPLY_BODY}" \ -o "${APPLY_BODY}" \
-w "%{http_code}" \ -w "%{http_code}" \
"${ACTIVE_PORTAINER_BASE_URL}/api/stacks/${STACK_ID}?endpointId=${PORTAINER_ENDPOINT_ID}" \ "${REQUEST_URL}" \
-H "X-API-Key: ${PORTAINER_API_KEY}" \ -H "X-API-Key: ${PORTAINER_API_KEY}" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "${PAYLOAD}" \ -d "${PAYLOAD}" \
@@ -164,17 +178,23 @@ jobs:
APPLY_CURL_EXIT=$? APPLY_CURL_EXIT=$?
else else
echo "Creating new stack ${STACK_NAME}" echo "Creating new stack ${STACK_NAME}"
REQUEST_URL="${ACTIVE_PORTAINER_BASE_URL}/api/stacks/create/standalone/string?endpointId=${PORTAINER_ENDPOINT_ID}"
PAYLOAD=$(jq -n \ PAYLOAD=$(jq -n \
--arg name "${STACK_NAME}" \ --arg name "${STACK_NAME}" \
--rawfile stack_file docker-compose.prod.yml \ --rawfile stack_file docker-compose.prod.yml \
--argjson env_vars "${ENV_JSON}" \ --argjson env_vars "${ENV_JSON}" \
'{Name: $name, StackFileContent: $stack_file, Env: $env_vars, FromAppTemplate: false}') '{Name: $name, StackFileContent: $stack_file, Env: $env_vars, FromAppTemplate: false}')
echo "Apply request URL: ${REQUEST_URL}"
echo "Apply payload summary:"
printf '%s' "${PAYLOAD}" | jq -r '{name: .Name, stackFileLength: (.StackFileContent | length), envCount: (.Env | length), fromAppTemplate: .FromAppTemplate}' || true
APPLY_HTTP_CODE=$(curl -sS -X POST \ APPLY_HTTP_CODE=$(curl -sS -X POST \
--noproxy "*" \ --noproxy "*" \
-D "${APPLY_HEADERS}" \
-o "${APPLY_BODY}" \ -o "${APPLY_BODY}" \
-w "%{http_code}" \ -w "%{http_code}" \
"${ACTIVE_PORTAINER_BASE_URL}/api/stacks/create/standalone/string?endpointId=${PORTAINER_ENDPOINT_ID}" \ "${REQUEST_URL}" \
-H "X-API-Key: ${PORTAINER_API_KEY}" \ -H "X-API-Key: ${PORTAINER_API_KEY}" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "${PAYLOAD}" \ -d "${PAYLOAD}" \
@@ -184,6 +204,8 @@ jobs:
echo "Apply curl exit: ${APPLY_CURL_EXIT}" echo "Apply curl exit: ${APPLY_CURL_EXIT}"
echo "Apply http code: ${APPLY_HTTP_CODE}" echo "Apply http code: ${APPLY_HTTP_CODE}"
echo "Apply response headers:"
cat "${APPLY_HEADERS}" || true
if [ "${APPLY_CURL_EXIT}" -ne 0 ]; then if [ "${APPLY_CURL_EXIT}" -ne 0 ]; then
echo "Apply stderr:" echo "Apply stderr:"
@@ -194,6 +216,24 @@ jobs:
if [ "${APPLY_HTTP_CODE}" -lt 200 ] || [ "${APPLY_HTTP_CODE}" -ge 300 ]; then if [ "${APPLY_HTTP_CODE}" -lt 200 ] || [ "${APPLY_HTTP_CODE}" -ge 300 ]; then
echo "Apply response body:" echo "Apply response body:"
cat "${APPLY_BODY}" || true cat "${APPLY_BODY}" || true
echo "Apply response parsed as JSON (if possible):"
jq -r '.' "${APPLY_BODY}" 2>/dev/null || echo "<non-json or empty body>"
if [ ! -s "${APPLY_BODY}" ]; then
echo "Apply body is empty; retrying once with verbose curl for diagnostics"
curl -v -X "$( [ -n "${STACK_ID}" ] && echo PUT || echo POST )" \
--noproxy "*" \
-o /tmp/portainer-debug-body.txt \
"${REQUEST_URL}" \
-H "X-API-Key: ${PORTAINER_API_KEY}" \
-H "Content-Type: application/json" \
-d "${PAYLOAD}" \
2>/tmp/portainer-debug-stderr.txt || true
echo "Verbose retry stderr:"
cat /tmp/portainer-debug-stderr.txt || true
echo "Verbose retry body:"
cat /tmp/portainer-debug-body.txt || true
fi
exit 1 exit 1
fi fi