Files
Gabriel Brown 8f09a423d4
Build and Push Next App / quality (push) Successful in 1m12s
Build and Push Next App / build-next (push) Successful in 2m20s
Read CI env from Infisical and give the local stack its own ports
CI reads Infisical staging as the read-only convexmonorepo-base-ci machine identity, runs the quality gate, and builds and pushes the image. The template is not deployed, so there is no Convex or VPS deploy step. The local stack moves to its own Compose name and ports so it runs beside the Payload template's, and it syncs the Convex runtime env. The scripts pick up Infisical account switching, dev-kill and a cache-safe CI install.
2026-10-01 14:55:35 -04:00

91 lines
3.6 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd -- "$SCRIPT_DIR/../.." && pwd)"
COMPOSE_FILE="$ROOT_DIR/docker/compose.local.yml"
STATE_FILE="$ROOT_DIR/.local/dev.generated.env"
ENV_FILE=""
info() { printf '▶ %s\n' "$*"; }
die() { printf 'Error: %s\n' "$*" >&2; exit 1; }
if command -v docker >/dev/null 2>&1; then RUNTIME=docker
elif command -v podman >/dev/null 2>&1; then RUNTIME=podman
else die "Docker or Podman is required."; fi
"$RUNTIME" info >/dev/null 2>&1 || die "$RUNTIME is not usable."
mkdir -p "$ROOT_DIR/.local"
cleanup() { [ -z "$ENV_FILE" ] || rm -f "$ENV_FILE"; }
trap cleanup EXIT
refresh_env() {
local next
next="$(mktemp "${TMPDIR:-/tmp}/convex-monorepo-local.XXXXXX.env")"
sh "$ROOT_DIR/scripts/export-env" dev > "$next" || { rm -f "$next"; die "Unable to export Infisical dev."; }
[ -z "$ENV_FILE" ] || rm -f "$ENV_FILE"
ENV_FILE="$next"
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
}
dc() { "$RUNTIME" compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" "$@"; }
upsert_state() {
local key="$1" value="$2" tmp escaped
tmp="$(mktemp "${TMPDIR:-/tmp}/convex-monorepo-state.XXXXXX.env")"
[ ! -f "$STATE_FILE" ] || grep -v "^${key}=" "$STATE_FILE" > "$tmp" || true
escaped="$(printf '%s' "$value" | sed "s/'/'\\\\''/g")"
printf "%s='%s'\n" "$key" "$escaped" >> "$tmp"
mv "$tmp" "$STATE_FILE"
}
refresh_env
info "Starting local Convex and dashboard"
dc up -d
info "Waiting for Convex at http://localhost:${BACKEND_PORT:-3250}"
for i in $(seq 1 60); do
curl -fs "http://localhost:${BACKEND_PORT:-3250}/version" >/dev/null 2>&1 && break
[ "$i" -lt 60 ] || die "Convex did not become ready."
sleep 2
done
if [ -z "${CONVEX_SELF_HOSTED_ADMIN_KEY:-}" ]; then
admin_key="$(dc exec -T convex-backend ./generate_admin_key.sh 2>/dev/null | grep -E '.+\|.+' | tail -n1 | tr -d '\r')"
[ -n "$admin_key" ] || die "Unable to generate the Convex admin key."
upsert_state CONVEX_SELF_HOSTED_ADMIN_KEY "$admin_key"
refresh_env
info "Generated the machine-local Convex admin key"
fi
info "Deploying Convex schema and functions"
(cd "$ROOT_DIR/packages/backend" && bun run setup)
# Env sync runs after the deploy: changing deployment env re-analyzes the
# deployed modules, which fails on a fresh volume before the first deploy.
info "Synchronizing the Convex function runtime environment"
sh "$ROOT_DIR/scripts/with-env" dev -- bash "$ROOT_DIR/scripts/sync-local-convex-env"
convex_env_names="$(
sh "$ROOT_DIR/scripts/with-env" dev -- bash -c \
'cd packages/backend && bunx convex env list' 2>/dev/null \
| sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=.*/\1/p'
)"
if ! printf '%s\n' "$convex_env_names" | grep -qx 'JWT_PRIVATE_KEY' \
|| ! printf '%s\n' "$convex_env_names" | grep -qx 'JWKS' \
|| ! printf '%s\n' "$convex_env_names" | grep -qx 'SITE_URL'; then
info "Configuring local Convex Auth keys"
auth_keys="$(node "$ROOT_DIR/scripts/generate-convex-auth-keys.mjs")"
jwt="$(printf '%s\n' "$auth_keys" | sed -n 's/^JWT_PRIVATE_KEY="\(.*\)"$/\1/p')"
jwks="$(printf '%s\n' "$auth_keys" | sed -n 's/^JWKS=//p')"
JWT_VAL="$jwt" JWKS_VAL="$jwks" sh "$ROOT_DIR/scripts/with-env" dev -- bash -c '
cd packages/backend
bunx convex env set "JWT_PRIVATE_KEY=$JWT_VAL" >/dev/null
bunx convex env set "JWKS=$JWKS_VAL" >/dev/null
bunx convex env set "SITE_URL=http://localhost:3000" >/dev/null
'
fi
printf '\nLocal stack ready:\n App: http://localhost:3000\n Convex: http://localhost:%s\n Dashboard: http://localhost:%s\n' "${BACKEND_PORT:-3250}" "${DASHBOARD_PORT:-6795}"