tenseleyflow/shithub / abd11cb

Browse files

deploy: provision-do.sh — fix stdout pollution in droplet/space helpers; split volume create/attach for re-run safety

Authored by espadonne
SHA
abd11cb1119f3f9b1281aaa5737f62303beb72d2
Parents
9df9065
Tree
05dc96c

1 changed file

StatusFile+-
M deploy/cutover/provision-do.sh 29 17
deploy/cutover/provision-do.shmodified
@@ -78,19 +78,22 @@ if [[ -z "$PROJECT_ID" ]]; then
7878
     --description "shithub.sh production environment" \
7979
     --no-header --format ID)"
8080
 fi
81
-echo "project: $PROJECT_NAME (id $PROJECT_ID)"
81
+echo "project: $PROJECT_NAME (id $PROJECT_ID)" >&2
8282
 
8383
 # --- 2. Droplets ---
84
+# Status messages must go to stderr so they don't pollute the captured
85
+# stdout (which the caller assigns to APP_ID etc.). Only the bare ID
86
+# goes to stdout.
8487
 create_or_skip_droplet() {
8588
   local name="$1" size="$2" tag="$3"
8689
   local existing
8790
   existing="$(doctl compute droplet list --no-header --format ID,Name | awk -v n="$name" '$2==n {print $1; exit}')"
8891
   if [[ -n "$existing" ]]; then
89
-    echo "droplet $name already exists (id $existing); skipping"
92
+    echo "droplet $name already exists (id $existing); skipping" >&2
9093
     echo "$existing"
9194
     return
9295
   fi
93
-  echo "creating droplet $name (size $size)..."
96
+  echo "creating droplet $name (size $size)..." >&2
9497
   local id
9598
   id="$(doctl compute droplet create "$name" \
9699
     --image ubuntu-24-04-x64 \
@@ -110,38 +113,47 @@ BAK_ID="$(create_or_skip_droplet shithub-backup s-1vcpu-2gb shithub-backup)"
110113
 MON_ID="$(create_or_skip_droplet shithub-monitoring s-2vcpu-4gb shithub-monitoring)"
111114
 
112115
 # --- 3. Block volume + attach to shithub-app ---
116
+# Volume creation and attach are independent steps; on a re-run we may
117
+# find the volume created but never attached (if a prior run died here).
118
+# Handle both checks separately.
113119
 VOL_NAME="shithub-data"
114120
 VOL_ID="$(doctl compute volume list --no-header --format ID,Name | awk -v n="$VOL_NAME" '$2==n {print $1; exit}')"
115121
 if [[ -z "$VOL_ID" ]]; then
116
-  echo "creating 100 GB volume $VOL_NAME..."
122
+  echo "creating 100 GB volume $VOL_NAME..." >&2
117123
   VOL_ID="$(doctl compute volume create "$VOL_NAME" \
118124
     --region "$PRIMARY_REGION" \
119125
     --size 100GiB \
120126
     --fs-type ext4 \
121127
     --no-header --format ID)"
122
-  echo "attaching $VOL_NAME to shithub-app..."
123
-  doctl compute volume-action attach "$VOL_ID" "$APP_ID" --wait
124128
 else
125
-  echo "volume $VOL_NAME already exists (id $VOL_ID); skipping create"
129
+  echo "volume $VOL_NAME already exists (id $VOL_ID); skipping create" >&2
130
+fi
131
+
132
+# Check whether the volume is already attached. doctl prints DropletIDs
133
+# as a JSON-style array like [123456789] or [].
134
+ATTACHED_TO="$(doctl compute volume get "$VOL_ID" --no-header --format DropletIDs | tr -d '[]' | xargs)"
135
+if [[ -z "$ATTACHED_TO" ]]; then
136
+  echo "attaching $VOL_NAME to shithub-app (id $APP_ID)..." >&2
137
+  doctl compute volume-action attach "$VOL_ID" "$APP_ID" --wait >&2
138
+else
139
+  echo "volume $VOL_NAME already attached to droplet(s) $ATTACHED_TO; skipping" >&2
126140
 fi
127141
 
128142
 # --- 4. Spaces buckets ---
129
-# doctl's spaces support exists but is limited; fall through to the s3-compatible API
130
-# via the standard awscli isn't worth the extra dep here. We use doctl's native
131
-# Spaces commands where they exist, and fall back to instructions for the rest.
143
+# doctl's spaces support varies by version. We attempt the native commands;
144
+# if they're not present, we print a fallback and continue.
132145
 create_or_skip_space() {
133146
   local name="$1" region="$2"
134
-  if doctl spaces buckets list --no-header --format Name | grep -qx "$name" 2>/dev/null; then
135
-    echo "Spaces bucket $name already exists; skipping"
147
+  if doctl spaces buckets list --no-header --format Name 2>/dev/null | grep -qx "$name"; then
148
+    echo "Spaces bucket $name already exists; skipping" >&2
136149
     return
137150
   fi
138
-  echo "creating Spaces bucket $name in $region..."
139
-  # Newer doctl versions support `doctl spaces buckets create`; older ones don't.
151
+  echo "creating Spaces bucket $name in $region..." >&2
140152
   if doctl spaces buckets create "$name" --region "$region" >/dev/null 2>&1; then
141
-    echo "  ok"
153
+    echo "  ok" >&2
142154
   else
143
-    echo "  doctl can't create the bucket (CLI version doesn't support it);"
144
-    echo "  create '$name' in region '$region' via the dashboard."
155
+    echo "  doctl can't create the bucket (CLI version may not support it);" >&2
156
+    echo "  create '$name' in region '$region' via the dashboard." >&2
145157
   fi
146158
 }
147159