mirror of
https://github.com/djdevin/recflare.git
synced 2026-09-08 14:41:28 -07:00
339a91735b
* turnstile * require turnstile * homepage refresh * implemented rooms visited endpoint for friends * update default profile pic * add a meta download button * add subroom permissions * enable signup
197 lines
8.0 KiB
Bash
Executable File
197 lines
8.0 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
. "$(git rev-parse --show-toplevel)/packages/tools/src/sh/env.sh"
|
|
|
|
# Extract name and version from package.json using jq
|
|
NAME=$(jq -r '.name' package.json)
|
|
VERSION=$(get-version)
|
|
|
|
# Everything an operator supplies — domain, resource ids, tuning knobs — comes from the
|
|
# single gitignored .env at the repo root (in CI, from exported secrets, which win over the
|
|
# file). See .env.example.
|
|
recflare_load_env
|
|
|
|
# Resolve the base domain (and this worker's subdomain), then deploy onto the
|
|
# custom domain via `--domain`. This keeps the real domain out of versioned files
|
|
# — committed wrangler.jsonc has no routes, and the base domain is passed as the
|
|
# DOMAIN var at runtime. Per-app subdomain overrides come from RECFLARE_SUBDOMAINS
|
|
# (a JSON object, e.g. {"playersettings":"settings"}).
|
|
if [ -z "${RECFLARE_DOMAIN:-}" ]; then
|
|
echo "error: RECFLARE_DOMAIN is not set — export it or add it to .env (see .env.example)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
DOMAIN="$RECFLARE_DOMAIN"
|
|
SUBDOMAINS_JSON=${RECFLARE_SUBDOMAINS:-}
|
|
[ -n "$SUBDOMAINS_JSON" ] || SUBDOMAINS_JSON='{}'
|
|
|
|
DIR=$(basename "$PWD")
|
|
# Per-app subdomain override, falling back to the worker's directory name.
|
|
SUBDOMAIN=$(printf '%s' "$SUBDOMAINS_JSON" | jq -r --arg d "$DIR" '.[$d] // $d')
|
|
HOST="$SUBDOMAIN.$DOMAIN"
|
|
|
|
# Splice deploy-time resource ids into a generated config. The committed
|
|
# wrangler.jsonc carries "local" placeholders so it needs no per-developer edits;
|
|
# the real ids stay in the gitignored .env / CI secrets. Workers without these
|
|
# bindings simply have no placeholder to replace.
|
|
#
|
|
# D1 — RECFLARE_D1: a single id (all workers share the one `recflare` database).
|
|
# KV — RECFLARE_KV: a JSON object keyed by binding name, since each KV namespace
|
|
# is distinct, e.g. {"RECFLARE_MATCH_PRESENCE":"…","RECFLARE_PLAYER_SETTINGS":"…"}.
|
|
# Secrets Store — RECFLARE_SECRETS_STORE: a single store id (all workers bind the
|
|
# one shared store for the JWT signing key).
|
|
CONFIG="wrangler.jsonc"
|
|
|
|
# Workers built with @cloudflare/vite-plugin (e.g. the React SPA in www) emit a
|
|
# deploy-ready config into dist/<dir>/ that carries the built worker
|
|
# (main: index.js), the resolved assets.directory, and no_bundle. The committed
|
|
# wrangler.jsonc leaves assets.directory out on purpose — the plugin fills it in —
|
|
# so deploying the source config fails with "assets ... missing the required
|
|
# directory property". Prefer the generated config when it exists.
|
|
#
|
|
# The plugin copies the bindings across verbatim, placeholders and all, so these
|
|
# configs need the same id-splicing as the rest — www binds the Secrets Store for its
|
|
# Turnstile keys. It gets its own branch below because the emitted file is minified
|
|
# single-line JSON, which the line-oriented sed/awk passes can't edit correctly.
|
|
VITE_CONFIG="dist/$DIR/wrangler.json"
|
|
IS_VITE=""
|
|
if [ -f "$VITE_CONFIG" ]; then
|
|
CONFIG="$VITE_CONFIG"
|
|
IS_VITE=1
|
|
fi
|
|
|
|
NEEDS_D1=$(grep -q '"database_id": *"local"' "$CONFIG" 2>/dev/null && echo 1 || true)
|
|
NEEDS_KV=$(grep -q '"id": *"local"' "$CONFIG" 2>/dev/null && echo 1 || true)
|
|
NEEDS_STORE=$(grep -q '"store_id": *"local"' "$CONFIG" 2>/dev/null && echo 1 || true)
|
|
|
|
# Vite-built config: plain JSON, so jq does the splicing structurally (by binding
|
|
# name for KV) rather than by line. Written beside the original so its relative
|
|
# paths (main, assets.directory) still resolve. Gitignored; removed on exit.
|
|
if [ "$CONFIG" = "$VITE_CONFIG" ] && { [ -n "$NEEDS_D1" ] || [ -n "$NEEDS_KV" ] || [ -n "$NEEDS_STORE" ]; }; then
|
|
GENERATED="dist/$DIR/wrangler.generated.json"
|
|
trap 'rm -f "$GENERATED"' EXIT
|
|
|
|
if [ -n "$NEEDS_D1" ] && [ -z "${RECFLARE_D1:-}" ]; then
|
|
echo "error: RECFLARE_D1 is not set — add the recflare D1 id to .env (see .env.example)" >&2
|
|
exit 1
|
|
fi
|
|
if [ -n "$NEEDS_STORE" ] && [ -z "${RECFLARE_SECRETS_STORE:-}" ]; then
|
|
echo "error: RECFLARE_SECRETS_STORE is not set — add the secrets store id to .env (see .env.example)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
KV_JSON=${RECFLARE_KV:-}
|
|
[ -n "$KV_JSON" ] || KV_JSON='{}'
|
|
|
|
jq \
|
|
--arg db "${RECFLARE_D1:-}" \
|
|
--arg store "${RECFLARE_SECRETS_STORE:-}" \
|
|
--argjson kv "$KV_JSON" '
|
|
(.d1_databases // []) |= map(
|
|
if .database_id == "local" then .database_id = $db else . end
|
|
)
|
|
| (.kv_namespaces // []) |= map(
|
|
if .id == "local" then
|
|
.id = ($kv[.binding] //
|
|
error("no KV id for binding [" + .binding + "] in RECFLARE_KV — add it to .env (see .env.example)"))
|
|
else . end
|
|
)
|
|
| (.secrets_store_secrets // []) |= map(
|
|
if .store_id == "local" then .store_id = $store else . end
|
|
)
|
|
' "$VITE_CONFIG" >"$GENERATED" || exit 1
|
|
CONFIG="$GENERATED"
|
|
fi
|
|
|
|
if [ "$CONFIG" = "wrangler.jsonc" ] && { [ -n "$NEEDS_D1" ] || [ -n "$NEEDS_KV" ] || [ -n "$NEEDS_STORE" ]; }; then
|
|
CONFIG="wrangler.generated.jsonc"
|
|
# Generated alongside the original so its relative paths (main, migrations_dir)
|
|
# still resolve. Gitignored; removed on exit so `wrangler dev` is unaffected.
|
|
trap 'rm -f wrangler.generated.jsonc wrangler.generated.tmp' EXIT
|
|
cp wrangler.jsonc wrangler.generated.jsonc
|
|
|
|
if [ -n "$NEEDS_D1" ]; then
|
|
DB_ID=${RECFLARE_D1:-}
|
|
if [ -z "$DB_ID" ]; then
|
|
echo "error: RECFLARE_D1 is not set — add the recflare D1 id to .env (see .env.example)" >&2
|
|
exit 1
|
|
fi
|
|
sed -E 's/("database_id"[[:space:]]*:[[:space:]]*")[^"]*(")/\1'"$DB_ID"'\2/' \
|
|
wrangler.generated.jsonc >wrangler.generated.tmp
|
|
mv wrangler.generated.tmp wrangler.generated.jsonc
|
|
fi
|
|
|
|
if [ -n "$NEEDS_KV" ]; then
|
|
KV_JSON=${RECFLARE_KV:-}
|
|
[ -n "$KV_JSON" ] || KV_JSON='{}'
|
|
# Map binding name -> id, then replace each kv_namespaces `"id": "local"`
|
|
# with the id for its nearest preceding "binding" line. awk keeps state so
|
|
# multiple namespaces in one file each get the right id.
|
|
KV_PAIRS=$(printf '%s' "$KV_JSON" | jq -r 'to_entries[] | "\(.key)\t\(.value)"')
|
|
awk -v pairs="$KV_PAIRS" '
|
|
BEGIN {
|
|
n = split(pairs, lines, "\n")
|
|
for (i = 1; i <= n; i++) {
|
|
if (lines[i] == "") continue
|
|
t = index(lines[i], "\t")
|
|
id[substr(lines[i], 1, t - 1)] = substr(lines[i], t + 1)
|
|
}
|
|
}
|
|
/"binding"[[:space:]]*:/ {
|
|
b = $0
|
|
sub(/.*"binding"[[:space:]]*:[[:space:]]*"/, "", b)
|
|
sub(/".*/, "", b)
|
|
curbind = b
|
|
}
|
|
/"id"[[:space:]]*:[[:space:]]*"local"/ {
|
|
if (!(curbind in id)) {
|
|
print "error: no KV id for binding [" curbind "] in RECFLARE_KV — add it to .env (see .env.example)" >"/dev/stderr"
|
|
exit 3
|
|
}
|
|
sub(/"local"/, "\"" id[curbind] "\"")
|
|
}
|
|
{ print }
|
|
' wrangler.generated.jsonc >wrangler.generated.tmp || exit 1
|
|
mv wrangler.generated.tmp wrangler.generated.jsonc
|
|
fi
|
|
|
|
if [ -n "$NEEDS_STORE" ]; then
|
|
STORE_ID=${RECFLARE_SECRETS_STORE:-}
|
|
if [ -z "$STORE_ID" ]; then
|
|
echo "error: RECFLARE_SECRETS_STORE is not set — add the secrets store id to .env (see .env.example)" >&2
|
|
exit 1
|
|
fi
|
|
sed -E 's/("store_id"[[:space:]]*:[[:space:]]*")[^"]*(")/\1'"$STORE_ID"'\2/' \
|
|
wrangler.generated.jsonc >wrangler.generated.tmp
|
|
mv wrangler.generated.tmp wrangler.generated.jsonc
|
|
fi
|
|
fi
|
|
|
|
# The operator's tuning knobs, injected the same way as the resource ids above: each lives
|
|
# in the .env as RECFLARE_<VAR> and rides along as a `--var`. See recflare_vars in
|
|
# packages/tools/src/sh/env.sh. run-wrangler-dev passes the same flags, so one .env tunes
|
|
# both a deploy and a local dev server.
|
|
EXTRA_VARS=$(recflare_vars)
|
|
|
|
# Vite-built configs set no_bundle (vite already bundled and minified), which is
|
|
# incompatible with --minify. Only pass --minify when wrangler does the bundling.
|
|
# Keyed on IS_VITE, not on $CONFIG: the splicing above may have swapped $CONFIG for
|
|
# the generated copy, which is just as no_bundle as the file it came from.
|
|
MINIFY="--minify"
|
|
[ -n "$IS_VITE" ] && MINIFY=""
|
|
|
|
# Deploy with wrangler using the extracted values as binding variables
|
|
echo "Deploying worker $NAME version $VERSION to $HOST"
|
|
# $EXTRA_VARS is intentionally unquoted — it's a flag list to word-split, and every
|
|
# value in it is an integer, so there's nothing to split on inside a value.
|
|
wrangler deploy \
|
|
--config "$CONFIG" \
|
|
--var NAME:"$NAME" \
|
|
--var SENTRY_RELEASE:"$VERSION" \
|
|
--var DOMAIN:"$DOMAIN" \
|
|
$EXTRA_VARS \
|
|
--domain "$HOST" \
|
|
$MINIFY \
|
|
"$@"
|