Jelajahi Sumber

CI: domains.sh read-back tolerates Vercel list lag and value format

The first live run wrote api-pr-5765 (served by ns1.vercel-dns.com) but the
record list didn't show it within 6s. Compare values without case or trailing
dot, accept the authoritative nameserver's answer, retry for 30s, and print the
records found under the name when it still fails.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Andrey Yasko 2 minggu lalu
induk
melakukan
282639ddf6
1 mengubah file dengan 21 tambahan dan 5 penghapusan
  1. 21 5
      scripts/railway/domains.sh

+ 21 - 5
scripts/railway/domains.sh

@@ -84,25 +84,41 @@ dns_records() {
     echo "$all"
 }
 
+# Values compare without case or a trailing dot ("Host.example." == "host.example").
 dns_has() { # dns_has <name> <type> <value>
-    dns_records | jq -e --arg n "$1" --arg t "$2" --arg v "$3" 'any(.[]; .name == $n and .type == $t and .value == $v)' >/dev/null
+    dns_records | jq -e --arg n "$1" --arg t "$2" --arg v "$3" \
+        'def norm: ascii_downcase | rtrimstr("."); any(.[]; .name == $n and .type == $t and (.value | norm) == ($v | norm))' >/dev/null
+}
+
+# Vercel's authoritative answer for <name>.DNS_ZONE: what resolvers will actually get.
+dns_served() { # dns_served <name> <type> <value>
+    command -v dig >/dev/null || return 1
+    local want got
+    want=$(tr '[:upper:]' '[:lower:]' <<< "${3%.}")
+    got=$(dig +short +norecurse "$2" "$1.$DNS_ZONE" @ns1.vercel-dns.com 2>/dev/null | tr -d '"' | sed 's/\.$//' | tr '[:upper:]' '[:lower:]')
+    grep -qxF "$want" <<< "$got"
 }
 
 dns_upsert() { # dns_upsert <name> <type> <value>
     local name=$1 type=$2 value=$3 id val
     while read -r id val; do
         [ -n "$id" ] || continue
-        if [ "$val" = "$value" ]; then echo "dns: $type $name ok"; return; fi
+        if [ "$(tr '[:upper:]' '[:lower:]' <<< "${val%.}")" = "$(tr '[:upper:]' '[:lower:]' <<< "${value%.}")" ]; then echo "dns: $type $name ok"; return; fi
         vercel DELETE "/v2/domains/$DNS_ZONE/records/$id" >/dev/null
     done < <(dns_records | jq -r --arg n "$name" --arg t "$type" '.[] | select(.name == $n and .type == $t) | "\(.id) \(.value)"')
     vercel POST "/v2/domains/$DNS_ZONE/records" \
         "$(jq -nc --arg n "$name" --arg t "$type" --arg v "$value" '{name: $n, type: $t, value: $v, ttl: 60}')" >/dev/null
     # Read it back: a record that silently didn't stick left previews without an API host.
+    # Vercel's record list can lag the write, so its nameserver's answer counts too.
     local try
-    for try in 1 2 3; do
-        dns_has "$name" "$type" "$value" && { echo "dns: $type $name -> $value"; return; }
-        sleep 2
+    for try in $(seq 1 10); do
+        if dns_has "$name" "$type" "$value" || dns_served "$name" "$type" "$value"; then
+            echo "dns: $type $name -> $value"; return
+        fi
+        sleep 3
     done
+    echo "dns: records named $name in $DNS_ZONE:" >&2
+    dns_records | jq -c --arg n "$name" '.[] | select(.name == $n) | {id, type, value}' >&2
     die "dns: $type $name was not found after writing it"
 }