Move to infisical. Create local dev environment. Add ci gates. Modernize repo
This commit is contained in:
+9
-16
@@ -1,19 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
ENV_FILE="$ROOT_DIR/.env"
|
||||
COMPOSE_FILE="$ROOT_DIR/docker/compose.yml"
|
||||
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
echo "Error: env file not found at $ENV_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -a
|
||||
source "$ENV_FILE"
|
||||
set +a
|
||||
|
||||
docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" build "$NEXT_CONTAINER_NAME"
|
||||
ROOT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
ENVIRONMENT="${1:-staging}"
|
||||
[[ "$ENVIRONMENT" == dev || "$ENVIRONMENT" == staging ]] || { echo "usage: build-next-app [dev|staging]" >&2; exit 2; }
|
||||
ENV_FILE="${CI_ENV_FILE:-}"
|
||||
cleanup() { [[ -n "$ENV_FILE" && "$ENV_FILE" != "${CI_ENV_FILE:-}" ]] && rm -f "$ENV_FILE" || true; }
|
||||
trap cleanup EXIT
|
||||
if [[ -z "$ENV_FILE" && -z "${CI:-}" ]]; then ENV_FILE="$(mktemp)"; sh "$ROOT_DIR/scripts/export-env" "$ENVIRONMENT" > "$ENV_FILE"; fi
|
||||
args=(); [[ -z "$ENV_FILE" ]] || args+=(--env-file "$ENV_FILE")
|
||||
docker compose "${args[@]}" -f "$ROOT_DIR/docker/compose.yml" build convexmonorepo-next
|
||||
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
#!/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"
|
||||
PAYLOAD_SEED_MARKER="$ROOT_DIR/.local/payload-seed-state.env"
|
||||
WIPE=false
|
||||
[ "${1:-}" = "--wipe" ] && WIPE=true
|
||||
|
||||
if command -v docker >/dev/null 2>&1; then RUNTIME=docker
|
||||
elif command -v podman >/dev/null 2>&1; then RUNTIME=podman
|
||||
else echo "Docker or Podman not found; nothing to stop." >&2; exit 0; fi
|
||||
|
||||
ENV_FILE="$(mktemp "${TMPDIR:-/tmp}/convex-monorepo-local.XXXXXX.env")"
|
||||
trap 'rm -f "$ENV_FILE"' EXIT
|
||||
sh "$ROOT_DIR/scripts/export-env" dev > "$ENV_FILE"
|
||||
|
||||
if [ "$WIPE" = true ]; then
|
||||
"$RUNTIME" compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" down -v
|
||||
if [ -f "$STATE_FILE" ]; then
|
||||
tmp="${STATE_FILE}.tmp"
|
||||
grep -v '^CONVEX_SELF_HOSTED_ADMIN_KEY=' "$STATE_FILE" > "$tmp" || true
|
||||
mv "$tmp" "$STATE_FILE"
|
||||
fi
|
||||
rm -f "$PAYLOAD_SEED_MARKER"
|
||||
echo "Local stack and both data volumes removed; generated admin key and Payload seed marker cleared."
|
||||
else
|
||||
"$RUNTIME" compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" down
|
||||
echo "Local stack stopped; Payload and Convex data preserved."
|
||||
fi
|
||||
Executable
+114
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env bash
|
||||
# Restore the local Payload database from the local snapshot only when the
|
||||
# database has not already been seeded. Does not contact staging/production.
|
||||
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"
|
||||
SNAPSHOT="$ROOT_DIR/.local/payload-staging.dump"
|
||||
MARKER="$ROOT_DIR/.local/payload-seed-state.env"
|
||||
DEV_ENV=""
|
||||
FORCE=false
|
||||
ASSUME_YES=false
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--force) FORCE=true ;;
|
||||
--yes) ASSUME_YES=true ;;
|
||||
*) printf 'usage: seed-payload [--force] [--yes]\n' >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
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."
|
||||
|
||||
cleanup() { [ -z "$DEV_ENV" ] || rm -f "$DEV_ENV"; }
|
||||
trap cleanup EXIT INT TERM HUP
|
||||
|
||||
if [ ! -s "$SNAPSHOT" ]; then
|
||||
echo "No local Payload snapshot found at .local/payload-staging.dump; skipping Payload seed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p "$ROOT_DIR/.local"
|
||||
chmod 700 "$ROOT_DIR/.local"
|
||||
|
||||
next_is_running=false
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
ss -ltnH 'sport = :3000' | grep -q . && next_is_running=true
|
||||
elif command -v lsof >/dev/null 2>&1; then
|
||||
lsof -nP -iTCP:3000 -sTCP:LISTEN >/dev/null 2>&1 && next_is_running=true
|
||||
elif curl -sS --max-time 1 http://localhost:3000 >/dev/null 2>&1; then
|
||||
next_is_running=true
|
||||
fi
|
||||
if [ "$next_is_running" = true ]; then
|
||||
die "Next is running on port 3000. Stop bun dev:next before replacing Payload data."
|
||||
fi
|
||||
|
||||
DEV_ENV="$(mktemp "${TMPDIR:-/tmp}/convex-monorepo-dev.XXXXXX.env")"
|
||||
sh "$ROOT_DIR/scripts/export-env" dev > "$DEV_ENV"
|
||||
|
||||
bunx dotenv -e "$DEV_ENV" -- node -e '
|
||||
const raw = process.env.PAYLOAD_DB_URL;
|
||||
if (!raw) process.exit(2);
|
||||
const url = new URL(raw);
|
||||
const local = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1";
|
||||
if (!local) process.exit(3);
|
||||
' || die "Refusing to seed: dev PAYLOAD_DB_URL is not localhost."
|
||||
|
||||
dc() { "$RUNTIME" compose --env-file "$DEV_ENV" -f "$COMPOSE_FILE" "$@"; }
|
||||
POSTGRES_USER="$(bunx dotenv -e "$DEV_ENV" -- sh -c 'printf %s "$POSTGRES_USER"')"
|
||||
POSTGRES_DB="$(bunx dotenv -e "$DEV_ENV" -- sh -c 'printf %s "$POSTGRES_DB"')"
|
||||
[ -n "$POSTGRES_USER" ] && [ -n "$POSTGRES_DB" ] || die "Local Postgres configuration is incomplete."
|
||||
|
||||
info "Ensuring local Payload Postgres is running"
|
||||
dc up -d postgres >/dev/null
|
||||
for i in $(seq 1 30); do
|
||||
if dc exec -T postgres pg_isready -U "$POSTGRES_USER" >/dev/null 2>&1; then break; fi
|
||||
[ "$i" -lt 30 ] || die "Local Payload Postgres did not become ready."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
SNAPSHOT_HASH="$(sha256sum "$SNAPSHOT" | awk '{print $1}')"
|
||||
marker_exists=false
|
||||
|
||||
# Earlier versions stored this marker in the Payload database. Payload/Drizzle
|
||||
# treats unmanaged tables as drift and prompts to delete them during dev startup,
|
||||
# so keep seed state in .local/ and remove the legacy table from local DBs.
|
||||
dc exec -T postgres psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 \
|
||||
-c 'DROP TABLE IF EXISTS _local_seed_state' >/dev/null
|
||||
|
||||
if [ -s "$MARKER" ] && grep -qx "PAYLOAD_SNAPSHOT_SHA256=$SNAPSHOT_HASH" "$MARKER"; then
|
||||
marker_exists=true
|
||||
fi
|
||||
|
||||
if [ "$marker_exists" = true ] && [ "$FORCE" != true ]; then
|
||||
echo "Payload snapshot seed already applied; skipping. Use --force to restore again."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$FORCE" = true ] && [ "$ASSUME_YES" != true ]; then
|
||||
printf 'This will replace the LOCAL Payload database from .local/payload-staging.dump.\n'
|
||||
read -r -p 'Continue? [y/N] ' answer
|
||||
case "$answer" in y|Y|yes|YES) ;; *) echo "Cancelled."; exit 0 ;; esac
|
||||
fi
|
||||
|
||||
info "Restoring local Payload database from .local/payload-staging.dump"
|
||||
dc exec -T postgres dropdb --force --if-exists -U "$POSTGRES_USER" "$POSTGRES_DB"
|
||||
dc exec -T postgres createdb -U "$POSTGRES_USER" -O "$POSTGRES_USER" "$POSTGRES_DB"
|
||||
dc exec -T postgres pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" \
|
||||
--no-owner --no-acl --exit-on-error < "$SNAPSHOT"
|
||||
|
||||
{
|
||||
printf 'PAYLOAD_SNAPSHOT_SHA256=%s\n' "$SNAPSHOT_HASH"
|
||||
printf 'PAYLOAD_SNAPSHOT_SEEDED_AT=%s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
} > "$MARKER"
|
||||
chmod 600 "$MARKER"
|
||||
|
||||
echo "Payload snapshot seed applied."
|
||||
Executable
+92
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env bash
|
||||
# Refresh the local Payload seed snapshot from staging, then force-apply it to
|
||||
# the local development Payload database. Normal db:up never calls staging.
|
||||
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"
|
||||
SNAPSHOT="$ROOT_DIR/.local/payload-staging.dump"
|
||||
STAGING_ENV=""
|
||||
DEV_ENV=""
|
||||
SOURCE_PG_ENV=""
|
||||
ASSUME_YES=false
|
||||
[ "${1:-}" = "--yes" ] && ASSUME_YES=true
|
||||
|
||||
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"
|
||||
chmod 700 "$ROOT_DIR/.local"
|
||||
cleanup() {
|
||||
[ -z "$STAGING_ENV" ] || rm -f "$STAGING_ENV"
|
||||
[ -z "$DEV_ENV" ] || rm -f "$DEV_ENV"
|
||||
[ -z "$SOURCE_PG_ENV" ] || rm -f "$SOURCE_PG_ENV"
|
||||
rm -f "${SNAPSHOT}.tmp"
|
||||
}
|
||||
trap cleanup EXIT INT TERM HUP
|
||||
|
||||
STAGING_ENV="$(mktemp "${TMPDIR:-/tmp}/convex-monorepo-staging.XXXXXX.env")"
|
||||
DEV_ENV="$(mktemp "${TMPDIR:-/tmp}/convex-monorepo-dev.XXXXXX.env")"
|
||||
sh "$ROOT_DIR/scripts/export-env" staging > "$STAGING_ENV"
|
||||
sh "$ROOT_DIR/scripts/export-env" dev > "$DEV_ENV"
|
||||
|
||||
validate_url() {
|
||||
local env_file="$1" expected="$2"
|
||||
bunx dotenv -e "$env_file" -- node -e '
|
||||
const expected = process.argv[1];
|
||||
const raw = process.env.PAYLOAD_DB_URL;
|
||||
if (!raw) process.exit(2);
|
||||
const url = new URL(raw);
|
||||
const local = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1";
|
||||
if ((expected === "local") !== local) process.exit(3);
|
||||
' "$expected" || die "PAYLOAD_DB_URL safety check failed for the $expected environment."
|
||||
}
|
||||
|
||||
validate_url "$STAGING_ENV" remote
|
||||
validate_url "$DEV_ENV" local
|
||||
|
||||
next_is_running=false
|
||||
if command -v ss >/dev/null 2>&1; then
|
||||
ss -ltnH 'sport = :3000' | grep -q . && next_is_running=true
|
||||
elif command -v lsof >/dev/null 2>&1; then
|
||||
lsof -nP -iTCP:3000 -sTCP:LISTEN >/dev/null 2>&1 && next_is_running=true
|
||||
elif curl -sS --max-time 1 http://localhost:3000 >/dev/null 2>&1; then
|
||||
next_is_running=true
|
||||
fi
|
||||
if [ "$next_is_running" = true ]; then
|
||||
die "Next is running on port 3000. Stop bun dev:next before replacing Payload data."
|
||||
fi
|
||||
|
||||
SOURCE_PG_ENV="$(mktemp "${TMPDIR:-/tmp}/convex-monorepo-pg.XXXXXX.env")"
|
||||
PG_ENV_FILE="$SOURCE_PG_ENV" bunx dotenv -e "$STAGING_ENV" -- sh -c '
|
||||
umask 077
|
||||
printf "PGDATABASE=%s\n" "$PAYLOAD_DB_URL" > "$PG_ENV_FILE"
|
||||
'
|
||||
|
||||
if [ "$ASSUME_YES" != true ]; then
|
||||
printf 'This will download staging Payload data and replace the LOCAL Payload database.\n'
|
||||
printf 'The snapshot may contain user records and password hashes; it stays under .local/.\n'
|
||||
read -r -p 'Continue? [y/N] ' answer
|
||||
case "$answer" in y|Y|yes|YES) ;; *) echo "Cancelled."; exit 0 ;; esac
|
||||
fi
|
||||
|
||||
info "Exporting a read-only snapshot from staging Payload Postgres"
|
||||
"$RUNTIME" run --rm --network host --env-file "$SOURCE_PG_ENV" \
|
||||
docker.io/library/postgres:17 \
|
||||
sh -c 'exec pg_dump --dbname="$PGDATABASE" --format=custom --no-owner --no-acl' \
|
||||
> "${SNAPSHOT}.tmp"
|
||||
mv "${SNAPSHOT}.tmp" "$SNAPSHOT"
|
||||
chmod 600 "$SNAPSHOT"
|
||||
|
||||
info "Ensuring local Payload Postgres is running"
|
||||
bash "$ROOT_DIR/scripts/db/seed-payload" --force --yes
|
||||
|
||||
printf '\nLocal Payload seed snapshot refreshed and applied.\n'
|
||||
printf 'Snapshot: .local/payload-staging.dump\n'
|
||||
printf 'Normal db:up will reuse this snapshot and skip after .local/payload-seed-state.env exists.\n'
|
||||
Executable
+95
@@ -0,0 +1,95 @@
|
||||
#!/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 Payload Postgres, Convex, and dashboard"
|
||||
dc up -d
|
||||
|
||||
info "Waiting for Payload Postgres"
|
||||
for i in $(seq 1 30); do
|
||||
dc exec -T postgres pg_isready -U "${POSTGRES_USER:-convexmonorepo}" >/dev/null 2>&1 && break
|
||||
[ "$i" -lt 30 ] || die "Postgres did not become ready."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
info "Waiting for Convex at http://localhost:${BACKEND_PORT:-3210}"
|
||||
for i in $(seq 1 60); do
|
||||
curl -fs "http://localhost:${BACKEND_PORT:-3210}/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)
|
||||
|
||||
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
|
||||
|
||||
info "Seeding local Payload from snapshot if needed"
|
||||
bash "$ROOT_DIR/scripts/db/seed-payload" --yes
|
||||
|
||||
printf '\nLocal stack ready:\n App: http://localhost:3000\n Convex: http://localhost:%s\n Dashboard: http://localhost:%s\n Payload Postgres: localhost:%s\n' "${BACKEND_PORT:-3210}" "${DASHBOARD_PORT:-6791}" "${POSTGRES_PORT:-5432}"
|
||||
+18
-40
@@ -1,49 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
ENV_FILE="$ROOT_DIR/.env"
|
||||
ROOT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
COMPOSE_FILE="$ROOT_DIR/docker/compose.yml"
|
||||
ENVIRONMENT="${1:-staging}"
|
||||
if [[ "$ENVIRONMENT" == dev || "$ENVIRONMENT" == staging ]]; then shift || true; else ENVIRONMENT=staging; fi
|
||||
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
echo "Error: env file not found at $ENV_FILE" >&2
|
||||
exit 1
|
||||
ENV_FILE="${CI_ENV_FILE:-}"
|
||||
cleanup() { [[ -n "$ENV_FILE" && "$ENV_FILE" != "${CI_ENV_FILE:-}" ]] && rm -f "$ENV_FILE" || true; }
|
||||
trap cleanup EXIT
|
||||
if [[ -z "$ENV_FILE" && -z "${CI:-}" ]]; then
|
||||
ENV_FILE="$(mktemp "${TMPDIR:-/tmp}/convex-monorepo-compose.XXXXXX.env")"
|
||||
sh "$ROOT_DIR/scripts/export-env" "$ENVIRONMENT" > "$ENV_FILE"
|
||||
fi
|
||||
|
||||
if [ ! -f "$COMPOSE_FILE" ]; then
|
||||
echo "Error: compose file not found at $COMPOSE_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -a
|
||||
source "$ENV_FILE"
|
||||
set +a
|
||||
|
||||
translated_args=()
|
||||
|
||||
args=()
|
||||
[[ -z "$ENV_FILE" ]] || args+=(--env-file "$ENV_FILE")
|
||||
translated=()
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
backend)
|
||||
: "${BACKEND_CONTAINER_NAME:?BACKEND_CONTAINER_NAME is not set in .env}"
|
||||
translated_args+=("$BACKEND_CONTAINER_NAME")
|
||||
;;
|
||||
dashboard)
|
||||
: "${DASHBOARD_CONTAINER_NAME:?DASHBOARD_CONTAINER_NAME is not set in .env}"
|
||||
translated_args+=("$DASHBOARD_CONTAINER_NAME")
|
||||
;;
|
||||
next)
|
||||
: "${NEXT_CONTAINER_NAME:?NEXT_CONTAINER_NAME is not set in .env}"
|
||||
translated_args+=("$NEXT_CONTAINER_NAME")
|
||||
;;
|
||||
*)
|
||||
translated_args+=("$arg")
|
||||
;;
|
||||
esac
|
||||
case "$arg" in backend) translated+=(convexmonorepo-backend) ;; dashboard) translated+=(convexmonorepo-dashboard) ;; next) translated+=(convexmonorepo-next) ;; *) translated+=("$arg") ;; esac
|
||||
done
|
||||
|
||||
exec docker compose \
|
||||
--env-file "$ENV_FILE" \
|
||||
-f "$COMPOSE_FILE" \
|
||||
"${translated_args[@]}"
|
||||
set +e
|
||||
docker compose "${args[@]}" -f "$COMPOSE_FILE" "${translated[@]}"
|
||||
status=$?
|
||||
set -e
|
||||
exit "$status"
|
||||
|
||||
Executable
+10
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
if [ -n "${CI:-}" ]; then echo "CI detected; skipping local e2e."; exit 0; fi
|
||||
if [ -n "${SKIP_E2E:-}" ]; then echo "SKIP_E2E set; skipping local e2e."; exit 0; fi
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)"
|
||||
bash "$ROOT_DIR/scripts/db/up"
|
||||
echo "Local-stack smoke checks passed; no seeded browser flow is configured."
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
[ "$#" -eq 1 ] || { echo "usage: export-env <dev|staging>" >&2; exit 2; }
|
||||
ENVIRONMENT="$1"
|
||||
case "$ENVIRONMENT" in dev|staging) ;; *) echo "export-env: expected dev or staging" >&2; exit 2 ;; esac
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
STATE_FILE="$ROOT_DIR/.local/$ENVIRONMENT.generated.env"
|
||||
|
||||
if [ -n "${CI:-}" ]; then
|
||||
echo "export-env: refusing to export secrets in CI; use injected variables or CI_ENV_FILE." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ -f "$ROOT_DIR/.infisical.json" ] || { echo "export-env: run 'infisical init' in this repository." >&2; exit 1; }
|
||||
command -v infisical >/dev/null 2>&1 || { echo "export-env: Infisical CLI is required." >&2; exit 1; }
|
||||
|
||||
(cd "$ROOT_DIR" && infisical export --env="$ENVIRONMENT" --format=dotenv --silent) || {
|
||||
echo "export-env: failed to export '$ENVIRONMENT'; check login and project access." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ -f "$STATE_FILE" ]; then
|
||||
printf '\n'
|
||||
while IFS= read -r line || [ -n "$line" ]; do
|
||||
case "$line" in ''|'#'*) printf '%s\n' "$line"; continue ;; esac
|
||||
key=${line%%=*}
|
||||
value=${line#*=}
|
||||
case "$value" in \'*\') value=${value#\'}; value=${value%\'} ;; \"*\") value=${value#\"}; value=${value%\"} ;; esac
|
||||
escaped=$(printf '%s' "$value" | sed "s/'/'\\\\''/g")
|
||||
printf "%s='%s'\n" "$key" "$escaped"
|
||||
done < "$STATE_FILE"
|
||||
fi
|
||||
@@ -1,20 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
ENV_FILE="$ROOT_DIR/.env"
|
||||
COMPOSE_FILE="$ROOT_DIR/docker/compose.yml"
|
||||
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
echo "Error: env file not found at $ENV_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -a
|
||||
source "$ENV_FILE"
|
||||
set +a
|
||||
|
||||
docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" exec \
|
||||
"$BACKEND_CONTAINER_NAME" ./generate_admin_key.sh
|
||||
ROOT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
ENVIRONMENT="${1:-staging}"
|
||||
[[ "$ENVIRONMENT" == dev || "$ENVIRONMENT" == staging ]] || { echo "usage: generate-convex-admin-key [dev|staging]" >&2; exit 2; }
|
||||
ENV_FILE="$(mktemp)"; trap 'rm -f "$ENV_FILE"' EXIT
|
||||
sh "$ROOT_DIR/scripts/export-env" "$ENVIRONMENT" > "$ENV_FILE"
|
||||
docker compose --env-file "$ENV_FILE" -f "$ROOT_DIR/docker/compose.yml" exec convexmonorepo-backend ./generate_admin_key.sh
|
||||
|
||||
+7
-20
@@ -1,22 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
ENV_FILE="$ROOT_DIR/.env"
|
||||
COMPOSE_FILE="$ROOT_DIR/docker/compose.yml"
|
||||
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
echo "Error: env file not found at $ENV_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -a
|
||||
source "$ENV_FILE"
|
||||
set +a
|
||||
|
||||
docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" pull \
|
||||
"$BACKEND_CONTAINER_NAME" "$DASHBOARD_CONTAINER_NAME"
|
||||
docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" up -d \
|
||||
"$BACKEND_CONTAINER_NAME" "$DASHBOARD_CONTAINER_NAME"
|
||||
ROOT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
ENVIRONMENT="${1:-staging}"
|
||||
[[ "$ENVIRONMENT" == dev || "$ENVIRONMENT" == staging ]] || { echo "usage: update-convex [dev|staging]" >&2; exit 2; }
|
||||
ENV_FILE="$(mktemp)"; trap 'rm -f "$ENV_FILE"' EXIT
|
||||
sh "$ROOT_DIR/scripts/export-env" "$ENVIRONMENT" > "$ENV_FILE"
|
||||
docker compose --env-file "$ENV_FILE" -f "$ROOT_DIR/docker/compose.yml" pull convexmonorepo-backend convexmonorepo-dashboard
|
||||
docker compose --env-file "$ENV_FILE" -f "$ROOT_DIR/docker/compose.yml" up -d convexmonorepo-backend convexmonorepo-dashboard
|
||||
|
||||
+7
-18
@@ -1,20 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd -- "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
ENV_FILE="$ROOT_DIR/.env"
|
||||
COMPOSE_FILE="$ROOT_DIR/docker/compose.yml"
|
||||
|
||||
if [ ! -f "$ENV_FILE" ]; then
|
||||
echo "Error: env file not found at $ENV_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -a
|
||||
source "$ENV_FILE"
|
||||
set +a
|
||||
|
||||
docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" build "$NEXT_CONTAINER_NAME"
|
||||
docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" up -d "$NEXT_CONTAINER_NAME"
|
||||
ROOT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
ENVIRONMENT="${1:-staging}"
|
||||
[[ "$ENVIRONMENT" == dev || "$ENVIRONMENT" == staging ]] || { echo "usage: update-next-app [dev|staging]" >&2; exit 2; }
|
||||
ENV_FILE="$(mktemp)"; trap 'rm -f "$ENV_FILE"' EXIT
|
||||
sh "$ROOT_DIR/scripts/export-env" "$ENVIRONMENT" > "$ENV_FILE"
|
||||
docker compose --env-file "$ENV_FILE" -f "$ROOT_DIR/docker/compose.yml" build convexmonorepo-next
|
||||
docker compose --env-file "$ENV_FILE" -f "$ROOT_DIR/docker/compose.yml" up -d convexmonorepo-next
|
||||
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
if [ "$#" -lt 1 ]; then
|
||||
echo "usage: with-env <dev|staging> -- <command> [args...]" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
ENVIRONMENT="$1"
|
||||
shift
|
||||
[ "${1:-}" = "--" ] && shift
|
||||
[ "$#" -gt 0 ] || { echo "with-env: no command given" >&2; exit 2; }
|
||||
|
||||
case "$ENVIRONMENT" in dev|staging) ;; *) echo "with-env: expected dev or staging" >&2; exit 2 ;; esac
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
STATE_FILE="$ROOT_DIR/.local/$ENVIRONMENT.generated.env"
|
||||
|
||||
if [ -n "${CI:-}" ]; then
|
||||
export WITH_ENV_SOURCE=ci WITH_ENV_ENVIRONMENT="$ENVIRONMENT" WITH_ENV_STATE_FILE="$STATE_FILE"
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
command -v infisical >/dev/null 2>&1 || {
|
||||
echo "with-env: install Infisical, run 'infisical login', and link this repo with 'infisical init'." >&2
|
||||
exit 1
|
||||
}
|
||||
[ -f "$ROOT_DIR/.infisical.json" ] || { echo "with-env: .infisical.json is missing." >&2; exit 1; }
|
||||
|
||||
TMP_ENV="$(mktemp "${TMPDIR:-/tmp}/convex-monorepo-$ENVIRONMENT.XXXXXX.env")"
|
||||
trap 'rm -f "$TMP_ENV"' EXIT INT TERM HUP
|
||||
sh "$ROOT_DIR/scripts/export-env" "$ENVIRONMENT" > "$TMP_ENV"
|
||||
|
||||
export WITH_ENV_SOURCE=infisical WITH_ENV_ENVIRONMENT="$ENVIRONMENT" WITH_ENV_STATE_FILE="$STATE_FILE"
|
||||
set +e
|
||||
bunx dotenv -e "$TMP_ENV" -- "$@"
|
||||
status=$?
|
||||
set -e
|
||||
exit "$status"
|
||||
Reference in New Issue
Block a user