vela 0.14.2 → 0.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vela",
3
- "version": "0.14.2",
3
+ "version": "0.14.4",
4
4
  "type": "module",
5
5
  "description": "A CLI for creating and updating SvelteKit projects",
6
6
  "license": "MIT",
@@ -36,9 +36,9 @@
36
36
  "dependencies": {
37
37
  "@clack/prompts": "^1.7.0",
38
38
  "@faker-js/faker": "^10.6.0",
39
- "@velastack/patterns": "^0.3.2",
39
+ "@velastack/patterns": "^0.3.3",
40
40
  "@velastack/pocketbase-codegen": "^0.1.0",
41
- "annotate-json-schema": "^0.1.0",
41
+ "annotate-json-schema": "^0.1.1",
42
42
  "commander": "^13.1.0",
43
43
  "cross-spawn": "^7.0.6",
44
44
  "dedent": "^1.7.2",
@@ -157,9 +157,9 @@ PB_PORT=$(printf '%s' "$PORTS" | jq -r .pb)
157
157
  PRIMARY_DOMAIN=$(printf '%s' "$DOMAIN" | cut -d, -f1 | tr -d ' ')
158
158
  [ -n "$PRIMARY_DOMAIN" ] || PRIMARY_DOMAIN=$(printf '%s' "$MANAGED" | cut -d, -f1 | tr -d ' ')
159
159
  if [ -n "$PRIMARY_DOMAIN" ]; then
160
- ORIGIN="https://$PRIMARY_DOMAIN"
160
+ PRIMARY_URL="https://$PRIMARY_DOMAIN"
161
161
  else
162
- ORIGIN="http://127.0.0.1:$WEB_PORT"
162
+ PRIMARY_URL="http://127.0.0.1:$WEB_PORT"
163
163
  fi
164
164
 
165
165
  # Production secrets live in $ETC/env and are managed only by `vela env`.
@@ -172,7 +172,7 @@ runtime_tmp=$(mktemp "$ETC/.runtime.XXXXXX")
172
172
  printf 'NODE_ENV=production\n'
173
173
  printf 'HOST=127.0.0.1\n'
174
174
  printf 'PORT=%s\n' "$WEB_PORT"
175
- printf 'ORIGIN=%s\n' "$ORIGIN"
175
+ runtime_origin_lines "$DOMAIN" "$PRIMARY_URL"
176
176
  # Only an instance with a PocketBase gets pointed at one: a URL to a port
177
177
  # nothing listens on is not a setting, it is a trap. Kept for one more
178
178
  # deploy when the backend is being removed, so that a failed deploy can put
@@ -412,7 +412,7 @@ fi
412
412
  log "starting app on 127.0.0.1:$WEB_PORT"
413
413
  systemctl enable "$WEB_UNIT" >/dev/null 2>&1 || true
414
414
  systemctl restart "$WEB_UNIT"
415
- wait_for_http "http://127.0.0.1:$WEB_PORT$HEALTH_PATH" 60 0.5 \
415
+ wait_for_http "http://127.0.0.1:$WEB_PORT$HEALTH_PATH" 60 0.5 "$PRIMARY_DOMAIN" \
416
416
  || die "app did not become healthy at $HEALTH_PATH - journalctl -u $WEB_UNIT"
417
417
 
418
418
  ACTIVATED=1
@@ -431,7 +431,7 @@ fi
431
431
  state_merge "$INSTANCE" "$(jq -c -n \
432
432
  --arg app "$APP_ID" --arg name "$APP_NAME" --arg env "$ENV_TAG" \
433
433
  --arg instance "$INSTANCE" --arg release "$RELEASE" --arg previous "$PREVIOUS" \
434
- --arg domain "$DOMAIN" --arg managed "$MANAGED" --arg url "$ORIGIN" \
434
+ --arg domain "$DOMAIN" --arg managed "$MANAGED" --arg url "$PRIMARY_URL" \
435
435
  --arg health "$HEALTH_PATH" --arg pb "$PB_VERSION" \
436
436
  --arg sha "$GIT_SHA" --arg at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
437
437
  --argjson web "$WEB_PORT" --argjson pbport "$PB_PORT" --argjson backend "$BACKEND" \
@@ -530,6 +530,6 @@ fi
530
530
 
531
531
  emit_result \
532
532
  --arg instance "$INSTANCE" --arg release "$RELEASE" --arg domain "$DOMAIN" --arg managed "$MANAGED" \
533
- --arg url "$ORIGIN" --argjson web "$WEB_PORT" --argjson pb "$PB_PORT" --argjson su "$SU_CREATED" \
533
+ --arg url "$PRIMARY_URL" --argjson web "$WEB_PORT" --argjson pb "$PB_PORT" --argjson su "$SU_CREATED" \
534
534
  '{instance: $instance, release: $release, domain: $domain, managed: $managed, url: $url,
535
535
  webPort: $web, pbPort: $pb, superuserCreated: ($su == 1)}'
@@ -171,11 +171,17 @@ unit_active() { systemctl is-active --quiet "$1"; }
171
171
  # a health path behind auth). A 404 is not that: it is what a wrong
172
172
  # --health-path or a route that never mounted looks like, and it used to pass.
173
173
  # No `-f`: curl has to report the status of an error response, not fail on it.
174
+ #
175
+ # A fourth argument is the public host to ask as, the way Caddy would. An app
176
+ # serving several hosts has no pinned ORIGIN and tells its sites apart by
177
+ # `Host`; asked as 127.0.0.1 it may rightly answer that it serves no such site.
174
178
  wait_for_http() {
175
- local url=$1 attempts=${2:-60} delay=${3:-0.5} code
179
+ local url=$1 attempts=${2:-60} delay=${3:-0.5} host=${4:-} code
176
180
  local i=0
181
+ local -a as=()
182
+ [ -z "$host" ] || as=(-H "Host: $host" -H 'X-Forwarded-Proto: https')
177
183
  while [ "$i" -lt "$attempts" ]; do
178
- code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 5 "$url" 2>/dev/null || echo 000)
184
+ code=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 5 ${as[@]+"${as[@]}"} "$url" 2>/dev/null || echo 000)
179
185
  case "$code" in
180
186
  2*|3*|401|403) return 0 ;;
181
187
  esac
@@ -185,6 +191,43 @@ wait_for_http() {
185
191
  return 1
186
192
  }
187
193
 
194
+ # The public host an instance's health check should ask as: the host of the
195
+ # `url` its last deploy recorded, or nothing for an instance no domain points
196
+ # at (whose url is its own loopback address).
197
+ #
198
+ # usage: state_primary_host <instance>
199
+ state_primary_host() {
200
+ local url
201
+ url=$(state_get "$1" url 2>/dev/null) || return 0
202
+ case "$url" in
203
+ https://*) url=${url#https://}; printf '%s' "${url%%/*}" ;;
204
+ esac
205
+ }
206
+
207
+ # The lines of runtime.env that tell adapter-node what origin a request has.
208
+ #
209
+ # One served host: pin it with ORIGIN, so nothing a client sends can change
210
+ # what the app believes its own address is. Several hosts served directly
211
+ # (velastack.dev and velabase.dev from one app) cannot share an ORIGIN - the
212
+ # second host would render as the first and have its form posts refused as
213
+ # cross-site - so the origin comes from the request instead: `Host`, which
214
+ # Caddy passes through and only ever for the names in this instance's site
215
+ # block, and the scheme from the X-Forwarded-Proto Caddy sets itself.
216
+ #
217
+ # Managed velastack.app names do not count: beside a direct host they redirect
218
+ # at the edge rather than being served.
219
+ #
220
+ # usage: runtime_origin_lines <direct_hosts_csv> <primary_url>
221
+ runtime_origin_lines() {
222
+ local direct=$1 primary_url=$2 count
223
+ count=$(printf '%s' "$direct" | tr ',' '\n' | sed 's/^ *//; s/ *$//' | grep -c -v '^$' || true)
224
+ if [ "$count" -gt 1 ]; then
225
+ printf 'PROTOCOL_HEADER=x-forwarded-proto\n'
226
+ else
227
+ printf 'ORIGIN=%s\n' "$primary_url"
228
+ fi
229
+ }
230
+
188
231
  # How many migrations the current release has that the target release does not.
189
232
  # PocketBase reverts by count, so this is what `migrate down` needs.
190
233
  migrations_ahead() {
@@ -220,7 +220,7 @@ assert_superuser_auth "$PB_PORT" "$SU_EMAIL" "$SU_PASSWORD" \
220
220
 
221
221
  log "starting app on 127.0.0.1:$WEB_PORT"
222
222
  systemctl start "$WEB_UNIT"
223
- wait_for_http "http://127.0.0.1:$WEB_PORT$HEALTH_PATH" 60 0.5 \
223
+ wait_for_http "http://127.0.0.1:$WEB_PORT$HEALTH_PATH" 60 0.5 "$(state_primary_host "$INSTANCE")" \
224
224
  || die "app did not become healthy at $HEALTH_PATH - journalctl -u $WEB_UNIT"
225
225
 
226
226
  RESTORED=1
@@ -74,7 +74,7 @@ if [ "$BACKEND" = "true" ]; then
74
74
  || die "PocketBase did not become healthy after rollback"
75
75
  fi
76
76
  systemctl restart "$WEB_UNIT"
77
- wait_for_http "http://127.0.0.1:$WEB_PORT$HEALTH_PATH" 60 0.5 \
77
+ wait_for_http "http://127.0.0.1:$WEB_PORT$HEALTH_PATH" 60 0.5 "$(state_primary_host "$INSTANCE")" \
78
78
  || die "app did not become healthy after rollback"
79
79
 
80
80
  state_merge "$INSTANCE" "$(jq -c -n --arg t "$TARGET" --arg c "$CURRENT" \