Skip to content

Commit 70ac6f8

Browse files
katipallyCopilot
andcommitted
fix(ci): real root cause — drop timeout wrapper around notarytool info
`timeout` is a GNU coreutils binary and does NOT exist on macOS by default. Every notarytool info poll therefore failed instantly with command-not-found, which was swallowed by `2>/dev/null` and replaced with the synthetic {"status":"poll_error"} sentinel. Result: 40 consecutive poll_errors, zero diagnostics, and the loop always exhausted its cap. Fix: • Remove the `timeout 90` wrapper. `notarytool info` is a short HTTPS call. • Capture notarytool stderr to a temp file instead of /dev/null, and print it whenever a poll fails so future hangs are debuggable. • Keep the 60-minute poll cap. This is the actual reason every v2.2.0 Release run has failed, regardless of the cap size or other tweaks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 0f08fe1 commit 70ac6f8

1 file changed

Lines changed: 23 additions & 8 deletions

File tree

.github/workflows/release.yml

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -218,29 +218,44 @@ jobs:
218218
219219
# ── Poll with notarytool info (every 30 s, max 120 polls = 60 min) ──
220220
# We use short-lived `notarytool info` calls instead of the long-running
221-
# `notarytool wait`, which can hang indefinitely on beta runners when
222-
# the underlying HTTP connection drops or the response is delayed.
223-
# Each info call is wrapped with `timeout 90` so a hung TLS handshake
224-
# cannot block us for more than 90 seconds (some first-time accounts
225-
# see Apple take 20-45 minutes for extended validation).
221+
# `notarytool wait`, which has hung indefinitely on macos-26 beta runners
222+
# when the underlying HTTPS connection drops mid-stream.
223+
#
224+
# NOTE: We deliberately do NOT wrap with `timeout` — that binary does not
225+
# exist on macOS (it's GNU coreutils) and silently failed every poll in
226+
# earlier runs, producing 40 consecutive `poll_error` with no diagnostics.
227+
# `notarytool info` is a short HTTPS call and returns quickly on its own.
226228
echo "Polling notarization status (up to 60 min)..."
227229
FINAL_STATUS="in_progress"
228230
for ATTEMPT in $(seq 1 120); do
229231
sleep 30
230232
231-
INFO_JSON=$(timeout 90 xcrun notarytool info "${SUBMISSION_ID}" \
233+
INFO_STDERR=$(mktemp)
234+
INFO_JSON=$(xcrun notarytool info "${SUBMISSION_ID}" \
232235
--key /tmp/AuthKey.p8 \
233236
--key-id "${NOTARIZE_KEY_ID}" \
234237
--issuer "${NOTARIZE_ISSUER_ID}" \
235-
--output-format json 2>/dev/null \
236-
|| echo '{"status":"poll_error"}')
238+
--output-format json 2>"${INFO_STDERR}") || INFO_JSON='{"status":"poll_error"}'
237239
238240
FINAL_STATUS=$(echo "${INFO_JSON}" | \
239241
python3 -c "import json,sys; print(json.load(sys.stdin).get('status','unknown'))" \
240242
2>/dev/null || echo "parse_error")
241243
242244
echo " [$(printf '%03d' $ATTEMPT)/120] $(date -u '+%H:%M:%S UTC') — ${FINAL_STATUS}"
243245
246+
# Surface stderr from notarytool whenever the call failed so we can
247+
# actually diagnose problems (previously suppressed with 2>/dev/null).
248+
if [ "${FINAL_STATUS}" = "poll_error" ] || [ "${FINAL_STATUS}" = "parse_error" ] || [ "${FINAL_STATUS}" = "unknown" ]; then
249+
if [ -s "${INFO_STDERR}" ]; then
250+
echo " ↳ notarytool stderr:"
251+
sed 's/^/ /' "${INFO_STDERR}"
252+
fi
253+
if [ -n "${INFO_JSON}" ]; then
254+
echo " ↳ notarytool stdout: ${INFO_JSON}"
255+
fi
256+
fi
257+
rm -f "${INFO_STDERR}"
258+
244259
case "${FINAL_STATUS}" in
245260
Accepted)
246261
echo "✅ Notarization accepted by Apple"

0 commit comments

Comments
 (0)