From f62846b2966e0a3ffc93e718bbe44137d01c66b3 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Tue, 24 Feb 2026 08:58:23 +0000 Subject: fix migration scripts for non-interactive SSH and bash 5.3 01-fetch-events.sh: nak buffers output when stdout is not a TTY, causing it to hang silently in non-interactive SSH sessions. Wrap with 'script' to provide a pseudo-TTY, then strip the injected carriage returns and connection banner line from the output. 40-classify-actions.sh: bash 5.3 treats ${#assoc[@]} and array iteration as unbound variable errors under set -u when arrays are empty. Replace ${#assoc[@]} with explicit counters and guard array iterations with set +u/set -u. --- .../scripts/01-fetch-events.sh | 9 +++++- .../scripts/40-classify-actions.sh | 37 ++++++++++++++++++---- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/docs/archive/2026-01-relay-ngit-dev-migration/scripts/01-fetch-events.sh b/docs/archive/2026-01-relay-ngit-dev-migration/scripts/01-fetch-events.sh index e0d6f26..7079bb9 100755 --- a/docs/archive/2026-01-relay-ngit-dev-migration/scripts/01-fetch-events.sh +++ b/docs/archive/2026-01-relay-ngit-dev-migration/scripts/01-fetch-events.sh @@ -124,7 +124,14 @@ fetch_kind() { # Use --paginate to ensure we get all events, not just first page # nak outputs one event per line (JSONL format) - if ! nak req -k "$kind" --paginate "$relay" > "$output_file" 2>/dev/null; then + # NOTE: nak buffers output when stdout is not a TTY (e.g. non-interactive SSH). + # Use 'script' to provide a pseudo-TTY so nak flushes each line immediately. + # Then strip the nak connection banner ("connecting to ...") and carriage returns + # that 'script' injects into the output stream. + if ! script -q -c "nak req -k $kind --paginate $relay" /dev/null 2>/dev/null \ + | tr -d '\r' \ + | grep -v '^connecting to ' \ + > "$output_file"; then log_error "Failed to fetch $description from $relay" return 1 fi diff --git a/docs/archive/2026-01-relay-ngit-dev-migration/scripts/40-classify-actions.sh b/docs/archive/2026-01-relay-ngit-dev-migration/scripts/40-classify-actions.sh index 8b61636..94487e6 100755 --- a/docs/archive/2026-01-relay-ngit-dev-migration/scripts/40-classify-actions.sh +++ b/docs/archive/2026-01-relay-ngit-dev-migration/scripts/40-classify-actions.sh @@ -103,11 +103,13 @@ log_info "Building lookup tables..." # Build prod category lookup: repo|npub -> category declare -A PROD_CAT +PROD_CAT_COUNT=0 while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do repo="${repo// /}" # Remove all spaces npub="${npub// /}" # Remove all spaces [[ -z "$repo" || -z "$npub" ]] && continue PROD_CAT["$repo|$npub"]="cat1" + PROD_CAT_COUNT=$((PROD_CAT_COUNT + 1)) done < "$PROD_DIR/category1-complete-match.txt" while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do @@ -115,6 +117,7 @@ while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do npub="${npub// /}" [[ -z "$repo" || -z "$npub" ]] && continue PROD_CAT["$repo|$npub"]="cat2" + PROD_CAT_COUNT=$((PROD_CAT_COUNT + 1)) done < "$PROD_DIR/category2-empty-blank.txt" while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do @@ -122,6 +125,7 @@ while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do npub="${npub// /}" [[ -z "$repo" || -z "$npub" ]] && continue PROD_CAT["$repo|$npub"]="cat3" + PROD_CAT_COUNT=$((PROD_CAT_COUNT + 1)) done < "$PROD_DIR/category3-partial-match.txt" while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do @@ -129,17 +133,20 @@ while IFS='|' read -r repo npub rest || [[ -n "$repo" ]]; do npub="${npub// /}" [[ -z "$repo" || -z "$npub" ]] && continue PROD_CAT["$repo|$npub"]="cat4" + PROD_CAT_COUNT=$((PROD_CAT_COUNT + 1)) done < "$PROD_DIR/category4-no-match.txt" -log_info "Loaded ${#PROD_CAT[@]} prod entries" +log_info "Loaded $PROD_CAT_COUNT prod entries" # Build archive category lookup: repo|npub -> category declare -A ARCHIVE_CAT +ARCHIVE_CAT_COUNT=0 while IFS='|' read -r repo npub rest; do repo="${repo// /}" npub="${npub// /}" [[ -z "$repo" || -z "$npub" ]] && continue ARCHIVE_CAT["$repo|$npub"]="cat1" + ARCHIVE_CAT_COUNT=$((ARCHIVE_CAT_COUNT + 1)) done < "$ARCHIVE_DIR/category1-complete-match.txt" while IFS='|' read -r repo npub rest; do @@ -147,6 +154,7 @@ while IFS='|' read -r repo npub rest; do npub="${npub// /}" [[ -z "$repo" || -z "$npub" ]] && continue ARCHIVE_CAT["$repo|$npub"]="cat2" + ARCHIVE_CAT_COUNT=$((ARCHIVE_CAT_COUNT + 1)) done < "$ARCHIVE_DIR/category2-empty-blank.txt" while IFS='|' read -r repo npub rest; do @@ -154,6 +162,7 @@ while IFS='|' read -r repo npub rest; do npub="${npub// /}" [[ -z "$repo" || -z "$npub" ]] && continue ARCHIVE_CAT["$repo|$npub"]="cat3" + ARCHIVE_CAT_COUNT=$((ARCHIVE_CAT_COUNT + 1)) done < "$ARCHIVE_DIR/category3-partial-match.txt" while IFS='|' read -r repo npub rest; do @@ -161,9 +170,10 @@ while IFS='|' read -r repo npub rest; do npub="${npub// /}" [[ -z "$repo" || -z "$npub" ]] && continue ARCHIVE_CAT["$repo|$npub"]="cat4" + ARCHIVE_CAT_COUNT=$((ARCHIVE_CAT_COUNT + 1)) done < "$ARCHIVE_DIR/category4-no-match.txt" -log_info "Loaded ${#ARCHIVE_CAT[@]} archive entries" +log_info "Loaded $ARCHIVE_CAT_COUNT archive entries" # Build purgatory lookup: repo|npub -> 1 (if purgatory expired) declare -A PURGATORY @@ -237,7 +247,7 @@ process_deletions() { process_deletions "$PROD_DIR/raw/deletions.json" process_deletions "$ARCHIVE_DIR/raw/deletions.json" DELETED_COUNT=0 -[[ ${#DELETED[@]} -gt 0 ]] && DELETED_COUNT=${#DELETED[@]} +for _k in "${!DELETED[@]}"; do DELETED_COUNT=$((DELETED_COUNT + 1)); done log_info "Loaded $DELETED_COUNT deletion entries" # Build git ancestry lookup: repo|npub -> relationship (archive-ahead, prod-ahead, diverged, etc.) @@ -266,17 +276,20 @@ fi log_info "Building unique repo list..." declare -A ALL_REPOS +ALL_REPOS_COUNT=0 +set +u for key in "${!PROD_CAT[@]}"; do - ALL_REPOS["$key"]=1 + [[ -z "${ALL_REPOS[$key]+x}" ]] && { ALL_REPOS["$key"]=1; ALL_REPOS_COUNT=$((ALL_REPOS_COUNT + 1)); } done for key in "${!ARCHIVE_CAT[@]}"; do - ALL_REPOS["$key"]=1 + [[ -z "${ALL_REPOS[$key]+x}" ]] && { ALL_REPOS["$key"]=1; ALL_REPOS_COUNT=$((ALL_REPOS_COUNT + 1)); } done for key in "${!PURGATORY[@]}"; do - ALL_REPOS["$key"]=1 + [[ -z "${ALL_REPOS[$key]+x}" ]] && { ALL_REPOS["$key"]=1; ALL_REPOS_COUNT=$((ALL_REPOS_COUNT + 1)); } done +set -u -log_info "Total unique repos: ${#ALL_REPOS[@]}" +log_info "Total unique repos: $ALL_REPOS_COUNT" # ============================================================================ # Phase 3: Classify each repo according to revised decision tree @@ -351,6 +364,7 @@ cat_to_status() { } LOOP_COUNT=0 +set +u for key in "${!ALL_REPOS[@]}"; do LOOP_COUNT=$((LOOP_COUNT + 1)) [[ $((LOOP_COUNT % 100)) -eq 0 ]] && log_info "Processed $LOOP_COUNT repos..." @@ -473,6 +487,7 @@ for key in "${!ALL_REPOS[@]}"; do ;; esac done +set -u # ============================================================================ # Phase 4: Write output files @@ -488,9 +503,11 @@ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S+00:00") echo "# Generated: $TIMESTAMP" echo "# Format: repo | npub | prod_status | archive_status | context | reason" echo "#" + set +u for line in "${READY_LINES[@]}"; do echo "$line" done + set -u } > "$READY_FILE" # Write needs-resync.txt @@ -503,9 +520,11 @@ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S+00:00") echo "# purgatory-expired = archive tried to sync but failed (30min timeout)" echo "# none = archive never tried or announcement missing" echo "#" + set +u for line in "${RESYNC_LINES[@]}"; do echo "$line" done + set -u } > "$RESYNC_FILE" # Write manual-review.txt @@ -514,9 +533,11 @@ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S+00:00") echo "# Generated: $TIMESTAMP" echo "# Format: repo | npub | prod_status | archive_status | context | reason" echo "#" + set +u for line in "${REVIEW_LINES[@]}"; do echo "$line" done + set -u } > "$REVIEW_FILE" # ============================================================================ @@ -525,9 +546,11 @@ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S+00:00") log_info "Generating summary..." +set +u TOTAL_READY="${#READY_LINES[@]}" TOTAL_RESYNC="${#RESYNC_LINES[@]}" TOTAL_REVIEW="${#REVIEW_LINES[@]}" +set -u TOTAL=$((TOTAL_READY + TOTAL_RESYNC + TOTAL_REVIEW)) # Calculate percentages -- cgit v1.2.3