Build: Add network-failure fault tolerance to macOS signing (#25265)
This commit is contained in:
@@ -119,8 +119,96 @@ run_codesign "${CONTAINING_FOLDER}/${APP_NAME}"
|
|||||||
echo "Creating disk image ${DMG_NAME}"
|
echo "Creating disk image ${DMG_NAME}"
|
||||||
dmgbuild -s ${DMG_SETTINGS} -Dcontaining_folder="${CONTAINING_FOLDER}" -Dapp_name="${APP_NAME}" "${VOLUME_NAME}" "${DMG_NAME}"
|
dmgbuild -s ${DMG_SETTINGS} -Dcontaining_folder="${CONTAINING_FOLDER}" -Dapp_name="${APP_NAME}" "${VOLUME_NAME}" "${DMG_NAME}"
|
||||||
|
|
||||||
# Submit it for notarization (requires that an App Store API Key has been set up in the notarytool)
|
ID_FILE="${DMG_NAME}.notarization_id"
|
||||||
time xcrun notarytool submit --wait --keychain-profile "${KEYCHAIN_PROFILE}" "${DMG_NAME}"
|
|
||||||
|
|
||||||
# Assuming that notarization succeeded, it's a good practice to staple that notarization to the DMG
|
# Submit it for notarization (requires that an App Store API Key has been set up in the notarytool)
|
||||||
xcrun stapler staple "${DMG_NAME}"
|
# This is a *very slow* process, and occasionally the GitHub runners lose the internet connection for a short time
|
||||||
|
# during the run. So in order to be fault-tolerant, this script polls, instead of using --wait
|
||||||
|
submit_notarization_request() {
|
||||||
|
if [[ -s "$ID_FILE" ]]; then
|
||||||
|
cat "$ID_FILE"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
local out
|
||||||
|
if ! out=$(xcrun notarytool submit --keychain-profile "$KEYCHAIN_PROFILE" \
|
||||||
|
--output-format json --no-progress "$DMG_NAME" 2>&1); then
|
||||||
|
print -r -- "$out" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
# We asked for JSON output so we had something stable, but of course parsing JSON with ZSH is ugly, so a quick bit of
|
||||||
|
# Python does it instead...
|
||||||
|
local id
|
||||||
|
id=$(print -r -- "$out" |
|
||||||
|
/usr/bin/python3 -c 'import sys, json; print(json.load(sys.stdin).get("id",""))'
|
||||||
|
)
|
||||||
|
[[ -n "$id" ]] || { print -r -- "Could not parse submission id" >&2; return 1; }
|
||||||
|
print -r -- "$id" > "$ID_FILE"
|
||||||
|
print -r -- "$id" # ID is a string here, not an integer, so I can't just return it
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_for_notarization_result() {
|
||||||
|
local id="$1" attempt=0
|
||||||
|
while :; do
|
||||||
|
if xcrun notarytool wait "$id" --keychain-profile "$KEYCHAIN_PROFILE" \
|
||||||
|
--timeout 10m --no-progress >/dev/null; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
(( attempt++ ))
|
||||||
|
# If the failure was transient (timeout/HTTP/connection) just retry, but make sure to check to see if the problem
|
||||||
|
# was actually that the signing failed before retrying.
|
||||||
|
local tmp_json
|
||||||
|
tmp_json=$(mktemp)
|
||||||
|
trap 'rm -f "$tmp_json"' EXIT INT TERM
|
||||||
|
|
||||||
|
xcrun notarytool info "$id" --keychain-profile "$KEYCHAIN_PROFILE" --output-format json 2>/dev/null > "$tmp_json"
|
||||||
|
/usr/bin/python3 - "$tmp_json" <<'PY'
|
||||||
|
import sys, json
|
||||||
|
try:
|
||||||
|
with open(sys.argv[1]) as f:
|
||||||
|
s = (json.load(f).get("status") or "").lower()
|
||||||
|
if s in ("invalid", "rejected"):
|
||||||
|
sys.exit(2)
|
||||||
|
else:
|
||||||
|
sys.exit(0)
|
||||||
|
except Exception:
|
||||||
|
sys.exit(1)
|
||||||
|
PY
|
||||||
|
rc=$?
|
||||||
|
|
||||||
|
rm -f "$tmp_json"
|
||||||
|
|
||||||
|
if [[ $rc == 2 ]]; then
|
||||||
|
print -r -- "Notarization was not accepted by Apple:" >&2
|
||||||
|
xcrun notarytool log "$id" --keychain-profile "$KEYCHAIN_PROFILE" >&2
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $attempt -gt 120 ]]; then
|
||||||
|
print -r -- "🏳️ Notarization is taking too long, bailing out. 🏳️" >&2
|
||||||
|
return 4
|
||||||
|
fi
|
||||||
|
sleep $(( (attempt<6?2**attempt:60) + RANDOM%5 )) # Increasing timeout plus jitter for multi-run safety
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
if ! id="$(submit_notarization_request)"; then
|
||||||
|
print -r -- "❌ Failed to submit notarization request" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ -z "$id" ]]; then
|
||||||
|
print -r -- "❌ Submission succeeded but no ID was returned" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
print "Notarization submission ID: $id"
|
||||||
|
|
||||||
|
if wait_for_notarization_result "$id"; then
|
||||||
|
print "✅ Notarization succeeded. Stapling..."
|
||||||
|
xcrun stapler staple "$DMG_NAME"
|
||||||
|
print "Stapled: $DMG_NAME"
|
||||||
|
rm -f "$ID_FILE"
|
||||||
|
else
|
||||||
|
rc=$?
|
||||||
|
print "❌ Notarization failed (code $rc)." >&2
|
||||||
|
exit "$rc"
|
||||||
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user