From fe204598a2d5afda7239a2138258fe5726f95f9b Mon Sep 17 00:00:00 2001 From: Admin Date: Wed, 4 Mar 2026 14:00:31 +0500 Subject: [PATCH] fix(pb-init): rewrite ensure_field with pure sh/awk, fix HTTP status parsing The previous ensure_fields helper used python3 which is not available in alpine:3.19, causing exit 127 in the cloud init container. Replaced with ensure_field (per-field, no python/jq) that uses only busybox sh, wget, sed, and awk. Also fixed the HTTP status grep pattern in create_collection and ensure_field to match only the response header line (^ HTTP/) instead of the wget error line, eliminating the spurious 'unexpected status server' warnings. --- scripts/pb-init.sh | 67 ++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 38 deletions(-) diff --git a/scripts/pb-init.sh b/scripts/pb-init.sh index 30aa97a..1bb82b4 100755 --- a/scripts/pb-init.sh +++ b/scripts/pb-init.sh @@ -47,7 +47,7 @@ create_collection() { --header="Content-Type: application/json" \ --header="Authorization: Bearer $TOKEN" \ --post-data="$BODY" \ - "$PB_URL/api/collections" 2>&1 | grep "HTTP/" | tail -1 | awk '{print $2}') + "$PB_URL/api/collections" 2>&1 | grep "^ HTTP/" | awk '{print $2}') case "$STATUS" in 200|201) log "created collection: $NAME" ;; 400|422) log "collection already exists (skipped): $NAME" ;; @@ -55,56 +55,49 @@ create_collection() { esac } -# Patch a collection by name: adds any fields listed in FIELDS_JSON that are -# missing from the current schema. This is idempotent and safe to re-run. -ensure_fields() { - NAME="$1" - FIELDS_JSON="$2" # JSON array of field objects to guarantee exist +# ensure_field COLLECTION FIELD_NAME FIELD_TYPE +# +# Checks whether FIELD_NAME exists in COLLECTION's schema. If it is missing, +# sends a PATCH with the full current fields list plus the new field appended. +# Uses only busybox sh + wget + sed/awk — no python/jq required. +ensure_field() { + COLL="$1" + FIELD_NAME="$2" + FIELD_TYPE="$3" - # Fetch current schema - CURRENT=$(wget -qO- \ + SCHEMA=$(wget -qO- \ --header="Authorization: Bearer $TOKEN" \ - "$PB_URL/api/collections/$NAME" 2>/dev/null) + "$PB_URL/api/collections/$COLL" 2>/dev/null) - COLLECTION_ID=$(echo "$CURRENT" | sed 's/.*"id":"\([^"]*\)".*/\1/') - if [ -z "$COLLECTION_ID" ] || [ "$COLLECTION_ID" = "$CURRENT" ]; then - log "WARNING: could not get id for collection $NAME — skipping ensure_fields" + # Check if the field already exists (look for "name":"" in the fields array) + if echo "$SCHEMA" | grep -q "\"name\":\"$FIELD_NAME\""; then + log "field $COLL.$FIELD_NAME already exists — skipping" return fi - # Build merged fields list via a small python snippet - MERGED=$(python3 - "$CURRENT" "$FIELDS_JSON" <<'PYEOF' -import sys, json -current = json.loads(sys.argv[1]) -desired = json.loads(sys.argv[2]) -existing_names = {f["name"] for f in current.get("fields", [])} -all_fields = list(current.get("fields", [])) -added = [] -for f in desired: - if f["name"] not in existing_names: - all_fields.append(f) - added.append(f["name"]) -print(json.dumps({"fields": all_fields, "_added": added})) -PYEOF -) - - ADDED=$(echo "$MERGED" | python3 -c 'import sys,json; d=json.load(sys.stdin); print(",".join(d.get("_added",[])))' 2>/dev/null) - if [ -z "$ADDED" ]; then - log "collection $NAME schema up-to-date" + COLLECTION_ID=$(echo "$SCHEMA" | sed 's/.*"id":"\([^"]*\)".*/\1/') + if [ -z "$COLLECTION_ID" ] || [ "$COLLECTION_ID" = "$SCHEMA" ]; then + log "WARNING: could not get id for collection $COLL — skipping ensure_field" return fi - PATCH_BODY=$(echo "$MERGED" | python3 -c 'import sys,json; d=json.load(sys.stdin); d.pop("_added",None); print(json.dumps(d))' 2>/dev/null) + # Extract current fields array (everything between the outermost [ ] of "fields":[...]) + # and append the new field object before the closing bracket. + CURRENT_FIELDS=$(echo "$SCHEMA" | sed 's/.*"fields":\(\[.*\]\).*/\1/') + # Strip the trailing ] and append the new field + TRIMMED=$(echo "$CURRENT_FIELDS" | sed 's/]$//') + NEW_FIELDS="${TRIMMED},{\"name\":\"${FIELD_NAME}\",\"type\":\"${FIELD_TYPE}\"}]" + PATCH_BODY="{\"fields\":${NEW_FIELDS}}" STATUS=$(wget -qSO- \ --header="Content-Type: application/json" \ --header="Authorization: Bearer $TOKEN" \ --body-data="$PATCH_BODY" \ --method=PATCH \ - "$PB_URL/api/collections/$COLLECTION_ID" 2>&1 | grep "HTTP/" | tail -1 | awk '{print $2}') + "$PB_URL/api/collections/$COLLECTION_ID" 2>&1 | grep "^ HTTP/" | awk '{print $2}') case "$STATUS" in - 200|201) log "patched collection $NAME — added fields: $ADDED" ;; - *) log "WARNING: patch returned $STATUS for collection $NAME" ;; + 200|201) log "patched $COLL — added field: $FIELD_NAME ($FIELD_TYPE)" ;; + *) log "WARNING: patch returned $STATUS when adding $FIELD_NAME to $COLL" ;; esac } @@ -191,8 +184,6 @@ create_collection "app_users" '{ # ─── 5. Schema migrations (idempotent field additions) ─────────────────────── # Ensures fields added after initial deploy are present in existing instances. -ensure_fields "progress" '[ - {"name": "user_id", "type": "text"} -]' +ensure_field "progress" "user_id" "text" log "all collections ready"