diff --git a/.cursor/cloud-setup.sh b/.cursor/cloud-setup.sh index ff558f63..3c319cdf 100755 --- a/.cursor/cloud-setup.sh +++ b/.cursor/cloud-setup.sh @@ -2,22 +2,33 @@ # Cursor Cloud environment setup: deps are installed by environment.json's # `install`; this script brings up the local Postgres and builds the MINIMAL # synthetic database (docs/AGENT-OPS.md — agents never see stage/prod URLs). +# +# Uses native PostgreSQL — Cursor Cloud VMs cannot run Docker (no daemon / overlayfs). set -euo pipefail -sudo service docker start +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +cd "${REPO_ROOT}" + +bash "${SCRIPT_DIR}/ensure-postgres.sh" if [ ! -f .env ]; then - sed 's/YOUR_SECRET_HERE/cursor-cloud-local-secret/' .env.example > .env + sed \ + -e 's/YOUR_SECRET_HERE/cursor-cloud-local-secret/' \ + -e 's/YOUR_BLOB_TOKEN_HERE/vercel_blob_rw_cloud01_localplaceholder01/' \ + .env.example > .env echo "[cloud-setup] wrote .env from .env.example (local-only values)" fi -pnpm db:start - -# Dev database (teqo) and test database (teqo_test) — compose creates both. +# Dev database (teqo) and test database (teqo_test). +echo "[cloud-setup] migrating teqo..." pnpm migrate +echo "[cloud-setup] migrating teqo_test..." DATABASE_URL=postgresql://teqo:teqo@localhost:5432/teqo_test pnpm migrate +echo "[cloud-setup] seeding teqo..." pnpm db:seed:minimal +echo "[cloud-setup] seeding teqo_test..." DATABASE_URL=postgresql://teqo:teqo@localhost:5432/teqo_test pnpm db:seed:minimal echo "[cloud-setup] OK — minimal database ready (dev + test)." diff --git a/.cursor/ensure-postgres.sh b/.cursor/ensure-postgres.sh new file mode 100755 index 00000000..aaaf4832 --- /dev/null +++ b/.cursor/ensure-postgres.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# Cursor Cloud VMs have no Docker and cannot run docker compose (overlayfs fails inside +# the agent container). Native PostgreSQL matches the local DATABASE_URL contract. +set -euo pipefail + +PG_VERSION="${PG_VERSION:-16}" +PG_CLUSTER="${PG_CLUSTER:-main}" + +pg_ready() { + PGPASSWORD=teqo psql -h localhost -U teqo -d teqo -c 'SELECT 1' >/dev/null 2>&1 +} + +detect_pg_version() { + if [ -d "/etc/postgresql" ]; then + ls /etc/postgresql/ 2>/dev/null | sort -nr | head -1 + return 0 + fi + echo "${PG_VERSION}" +} + +start_postgres() { + if pg_ready; then + return 0 + fi + + local version + version="$(detect_pg_version)" + + if command -v pg_ctlcluster >/dev/null 2>&1 && [ -n "${version}" ]; then + sudo pg_ctlcluster "${version}" "${PG_CLUSTER}" start 2>/dev/null || true + sleep 2 + pg_ready && return 0 + fi + + if command -v systemctl >/dev/null 2>&1; then + sudo systemctl start "postgresql@${version}-${PG_CLUSTER}" 2>/dev/null || \ + sudo systemctl start postgresql 2>/dev/null || true + sleep 2 + pg_ready && return 0 + fi + + echo "[ensure-postgres] ERROR: postgres is installed but not accepting connections" >&2 + exit 1 +} + +bootstrap_databases() { + sudo -u postgres psql -v ON_ERROR_STOP=1 <<'SQL' +DO $$ +BEGIN + IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = 'teqo') THEN + CREATE ROLE teqo WITH LOGIN PASSWORD 'teqo' CREATEDB; + END IF; +END +$$; +SELECT 'CREATE DATABASE teqo OWNER teqo' +WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'teqo')\gexec +SELECT 'CREATE DATABASE teqo_test OWNER teqo' +WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'teqo_test')\gexec +SQL +} + +if command -v psql >/dev/null 2>&1 && [ -d "/etc/postgresql" ]; then + start_postgres + bootstrap_databases + pg_ready + echo "[ensure-postgres] OK (existing cluster)" + exit 0 +fi + +echo "[ensure-postgres] installing postgresql-${PG_VERSION} (Ubuntu package; local dev uses PG 17 via Docker)..." +sudo apt-get update -qq +sudo DEBIAN_FRONTEND=noninteractive apt-get install -y "postgresql-${PG_VERSION}" "postgresql-client-${PG_VERSION}" +start_postgres +bootstrap_databases +pg_ready +echo "[ensure-postgres] OK" diff --git a/.cursor/environment.json b/.cursor/environment.json index b22f7c13..d7191b92 100644 --- a/.cursor/environment.json +++ b/.cursor/environment.json @@ -1,4 +1,4 @@ { "install": "pnpm install --frozen-lockfile && bash ./.cursor/cloud-setup.sh", - "start": "sudo service docker start && pnpm db:start" + "start": "bash ./.cursor/ensure-postgres.sh" } diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml index ff1aa302..bd812aac 100644 --- a/.github/workflows/ci-pr.yml +++ b/.github/workflows/ci-pr.yml @@ -327,6 +327,7 @@ jobs: - name: Count open PRs touching schema files env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} run: | set -euo pipefail count=$(gh pr list --state open --limit 100 --json number,files \ diff --git a/docs/AGENT-OPS.md b/docs/AGENT-OPS.md index 04e25596..8c284791 100644 --- a/docs/AGENT-OPS.md +++ b/docs/AGENT-OPS.md @@ -70,7 +70,7 @@ Fast gate local do agente antes do push: `pnpm gate:fast` (lint + typecheck + te ## Cursor Cloud -`.cursor/environment.json` instala deps, sobe Postgres (compose), migra e roda `db:seed:minimal` — clone + `gh` + DB mínimo bastam. Sem secrets de stage/prod. Hooks do repo são portáteis (paths relativos em `.cursor/hooks.json`); hooks pessoais (ex.: impeccable) ficam no `~/.cursor/hooks.json` do usuário. +`.cursor/environment.json` instala deps, sobe Postgres nativo (`ensure-postgres.sh` — VMs Cloud não rodam Docker/compose), migra e roda `db:seed:minimal` — clone + `gh` + DB mínimo bastam. Sem secrets de stage/prod. Hooks do repo são portáteis (paths relativos em `.cursor/hooks.json`); hooks pessoais (ex.: impeccable) ficam no `~/.cursor/hooks.json` do usuário. ## Guardrails progressivos