refactor: update environment configuration, enhance installation script, and add migration scripts for database setup
This commit is contained in:
+20
-11
@@ -1,14 +1,23 @@
|
||||
# ─── Supabase (Zorunlu) ───────────────────────────────────────
|
||||
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
|
||||
# Neta self-host environment
|
||||
|
||||
# Müşteri Portalı hesabı oluşturmak için gerekli (Freelancer panelinde kullanılır)
|
||||
SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key
|
||||
# Public URL where users open Neta.
|
||||
NEXT_PUBLIC_SITE_URL=http://localhost:3000
|
||||
|
||||
# ─── AI Sağlayıcılar (Opsiyonel — uygulama içi ayarlardan da tanımlanabilir) ───
|
||||
# OPENAI_API_KEY=your_openai_api_key
|
||||
# GROQ_API_KEY=your_groq_api_key
|
||||
# GEMINI_API_KEY=your_gemini_api_key
|
||||
# Host port mapped to the Neta container's internal port 3000.
|
||||
NETA_PORT=3000
|
||||
|
||||
# ─── Supabase Auth (Self-host'ta gerekli olabilir) ───────────
|
||||
# NEXT_PUBLIC_SITE_URL=https://neta.example.com
|
||||
# Supabase API URL. For a hosted project this looks like:
|
||||
# https://your-project.supabase.co
|
||||
# For a bundled/self-hosted Supabase setup this is usually your public API URL.
|
||||
NEXT_PUBLIC_SUPABASE_URL=
|
||||
|
||||
# Supabase anon/public API key.
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=
|
||||
|
||||
# Supabase service role key. Required for creating client portal accounts.
|
||||
# Keep this secret. It is only used server-side.
|
||||
SUPABASE_SERVICE_ROLE_KEY=
|
||||
|
||||
# Optional: direct Postgres connection string used only by bash ./scripts/apply-migrations.sh.
|
||||
# Do not expose this to browsers. It is not required by the web container.
|
||||
# DATABASE_URL=postgresql://postgres:password@host:5432/postgres
|
||||
|
||||
@@ -50,32 +50,45 @@ Neta is engineered using modern, high-performance web technologies:
|
||||
|
||||
## Installation and Deployment
|
||||
|
||||
Neta is designed to be easily self-hosted. Follow these steps to deploy the application on your own infrastructure.
|
||||
Neta is designed for self-hosting. The current Docker Compose file runs the Neta web application and connects it to a Supabase-compatible backend. A bundled Supabase Compose profile is planned for the full-stack self-host mode.
|
||||
|
||||
### Prerequisites
|
||||
- Docker and Docker Compose
|
||||
- Node.js (for local development)
|
||||
- A Supabase instance (Cloud or Self-Hosted)
|
||||
- A Supabase project or self-hosted Supabase backend
|
||||
- Supabase API URL, anon key, and service role key
|
||||
- A direct Postgres `DATABASE_URL` if you want the installer to apply migrations automatically
|
||||
|
||||
### 1-Click Installation (Recommended)
|
||||
|
||||
You can install and start Neta immediately using our automated setup script. Simply run the following command in your terminal:
|
||||
You can install Neta using the interactive setup script:
|
||||
|
||||
```bash
|
||||
curl -sL https://raw.githubusercontent.com/poyrazavsever/neta/main/install.sh | bash
|
||||
```
|
||||
|
||||
The installer asks for the required Supabase values, writes a `.env` file, optionally applies database migrations, validates Docker Compose configuration, and starts the application.
|
||||
|
||||
### Manual Installation
|
||||
|
||||
If you prefer to set up Neta manually:
|
||||
|
||||
1. Clone the repository: `git clone https://github.com/poyrazavsever/neta.git`
|
||||
2. Navigate to the directory and copy the `.env.example` file to `.env.local`.
|
||||
3. Build and start the Docker container:
|
||||
2. Navigate to the directory and copy the `.env.example` file to `.env`.
|
||||
3. Fill every required value in `.env`.
|
||||
4. Apply database migrations:
|
||||
|
||||
```bash
|
||||
docker-compose up -d --build
|
||||
DATABASE_URL='postgresql://postgres:password@host:5432/postgres' bash ./scripts/apply-migrations.sh
|
||||
```
|
||||
|
||||
5. Build and start the Docker container:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
Docker Compose intentionally fails fast when required Supabase environment values are missing.
|
||||
|
||||
### First Administrator Account
|
||||
To ensure data security, Neta is locked to a single administrator. Upon launching the application for the first time, navigate to the `/register` route to create the initial admin account. Once this account is created, public registration is permanently disabled.
|
||||
|
||||
|
||||
+8
-10
@@ -4,18 +4,16 @@ services:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
NEXT_PUBLIC_SUPABASE_URL: ${NEXT_PUBLIC_SUPABASE_URL}
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${NEXT_PUBLIC_SUPABASE_ANON_KEY}
|
||||
NEXT_PUBLIC_SUPABASE_URL: ${NEXT_PUBLIC_SUPABASE_URL:?Set NEXT_PUBLIC_SUPABASE_URL in .env}
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${NEXT_PUBLIC_SUPABASE_ANON_KEY:?Set NEXT_PUBLIC_SUPABASE_ANON_KEY in .env}
|
||||
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:-http://localhost:3000}
|
||||
container_name: neta-web
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "${NETA_PORT:-3000}:3000"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- NEXT_PUBLIC_SUPABASE_URL=${NEXT_PUBLIC_SUPABASE_URL}
|
||||
- NEXT_PUBLIC_SUPABASE_ANON_KEY=${NEXT_PUBLIC_SUPABASE_ANON_KEY}
|
||||
- SUPABASE_SERVICE_ROLE_KEY=${SUPABASE_SERVICE_ROLE_KEY}
|
||||
- NEXT_PUBLIC_SITE_URL=${NEXT_PUBLIC_SITE_URL:-http://localhost:3000}
|
||||
env_file:
|
||||
- .env.local
|
||||
NODE_ENV: production
|
||||
NEXT_PUBLIC_SUPABASE_URL: ${NEXT_PUBLIC_SUPABASE_URL:?Set NEXT_PUBLIC_SUPABASE_URL in .env}
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${NEXT_PUBLIC_SUPABASE_ANON_KEY:?Set NEXT_PUBLIC_SUPABASE_ANON_KEY in .env}
|
||||
SUPABASE_SERVICE_ROLE_KEY: ${SUPABASE_SERVICE_ROLE_KEY:?Set SUPABASE_SERVICE_ROLE_KEY in .env}
|
||||
NEXT_PUBLIC_SITE_URL: ${NEXT_PUBLIC_SITE_URL:-http://localhost:3000}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# 0004 - Business OS Tables
|
||||
|
||||
SQL file: `supabase/migrations/0004_add_business_os_tables.sql`
|
||||
|
||||
## Purpose
|
||||
|
||||
Adds business document and recurring cost tables used by the freelancer business layer.
|
||||
|
||||
## What It Creates
|
||||
|
||||
- `proposals`
|
||||
- `contracts`
|
||||
- `invoices`
|
||||
- `subscriptions`
|
||||
|
||||
## RLS
|
||||
|
||||
Every table has `user_id` and row level security policies that allow users to select, insert, update, and delete only their own rows.
|
||||
|
||||
## Execution
|
||||
|
||||
Run after `0003_add_project_planning_assets.sql`.
|
||||
@@ -0,0 +1,28 @@
|
||||
# 0005 - Advanced CRM Tables
|
||||
|
||||
SQL file: `supabase/migrations/0005_add_advanced_crm_tables.sql`
|
||||
|
||||
## Purpose
|
||||
|
||||
Extends client management with pipeline and activity tracking fields.
|
||||
|
||||
## What It Changes
|
||||
|
||||
The `clients` table receives:
|
||||
|
||||
- `pipeline_stage`
|
||||
- `next_follow_up_date`
|
||||
- `last_contact_date`
|
||||
- `client_value_score`
|
||||
|
||||
## What It Creates
|
||||
|
||||
- `client_activities`
|
||||
|
||||
## RLS
|
||||
|
||||
`client_activities` is user-scoped through `user_id` and has select, insert, update, and delete policies for the owning user.
|
||||
|
||||
## Execution
|
||||
|
||||
Run after `0004_add_business_os_tables.sql`.
|
||||
@@ -0,0 +1,25 @@
|
||||
# 0006 - pgvector And Embeddings
|
||||
|
||||
SQL file: `supabase/migrations/0006_add_pgvector_and_embeddings.sql`
|
||||
|
||||
## Purpose
|
||||
|
||||
Adds vector storage for future retrieval augmented generation features.
|
||||
|
||||
## What It Creates
|
||||
|
||||
- `vector` extension
|
||||
- `document_embeddings`
|
||||
- `match_documents()`
|
||||
|
||||
## RLS
|
||||
|
||||
Embeddings are scoped by `user_id`; users can manage only their own embedding rows.
|
||||
|
||||
## Notes
|
||||
|
||||
The migration expects the target Postgres/Supabase environment to support the `vector` extension.
|
||||
|
||||
## Execution
|
||||
|
||||
Run after `0005_add_advanced_crm_tables.sql`.
|
||||
@@ -0,0 +1,25 @@
|
||||
# 0007 - Client Portal Tables
|
||||
|
||||
SQL file: `supabase/migrations/0007_add_client_portal_tables.sql`
|
||||
|
||||
## Purpose
|
||||
|
||||
Adds client portal access and revision request support.
|
||||
|
||||
## What It Changes
|
||||
|
||||
- Adds `profiles.role`
|
||||
- Adds `clients.client_auth_id`
|
||||
- Adds `tasks.is_public_to_client`
|
||||
|
||||
## What It Creates
|
||||
|
||||
- `project_revisions`
|
||||
|
||||
## RLS
|
||||
|
||||
Freelancers manage revisions for their own projects. Clients can view their linked client record, related projects, public project tasks, project planning sections, and their own revision requests.
|
||||
|
||||
## Execution
|
||||
|
||||
Run after `0006_add_pgvector_and_embeddings.sql`.
|
||||
@@ -0,0 +1,29 @@
|
||||
# 0008 - Project Progress And Quota
|
||||
|
||||
SQL file: `supabase/migrations/0008_add_project_progress_and_quota.sql`
|
||||
|
||||
## Purpose
|
||||
|
||||
Adds project progress mode and revision quota support.
|
||||
|
||||
## What It Changes
|
||||
|
||||
The `projects` table receives:
|
||||
|
||||
- `progress_type`
|
||||
- `revision_quota`
|
||||
|
||||
## What It Creates
|
||||
|
||||
- `update_project_progress_on_task_change()`
|
||||
- `trigger_update_project_progress`
|
||||
- `update_project_progress_on_type_change()`
|
||||
- `trigger_update_project_progress_type`
|
||||
|
||||
## Notes
|
||||
|
||||
Automatic progress mode calculates progress from tasks with status `done`.
|
||||
|
||||
## Execution
|
||||
|
||||
Run after `0007_add_client_portal_tables.sql`.
|
||||
@@ -7,6 +7,11 @@ This file is the canonical order of SQL files for database setup and migration.
|
||||
| 0001 | `supabase/schema.sql` | `docs/database/0001-initial-schema.md` | Baseline registered |
|
||||
| 0002 | `supabase/migrations/0002_add_freelancer_os_core_tables.sql` | `docs/database/0002-freelancer-os-core-tables.md` | Pending execution |
|
||||
| 0003 | `supabase/migrations/0003_add_project_planning_assets.sql` | `docs/database/0003-project-planning-assets.md` | Pending execution |
|
||||
| 0004 | `supabase/migrations/0004_add_business_os_tables.sql` | `docs/database/0004-business-os-tables.md` | Pending execution |
|
||||
| 0005 | `supabase/migrations/0005_add_advanced_crm_tables.sql` | `docs/database/0005-advanced-crm-tables.md` | Pending execution |
|
||||
| 0006 | `supabase/migrations/0006_add_pgvector_and_embeddings.sql` | `docs/database/0006-pgvector-and-embeddings.md` | Pending execution |
|
||||
| 0007 | `supabase/migrations/0007_add_client_portal_tables.sql` | `docs/database/0007-client-portal-tables.md` | Pending execution |
|
||||
| 0008 | `supabase/migrations/0008_add_project_progress_and_quota.sql` | `docs/database/0008-project-progress-and-quota.md` | Pending execution |
|
||||
| 0009 | `supabase/migrations/0009_lock_registration_after_first_admin.sql` | `docs/database/0009-lock-registration-after-first-admin.md` | Pending execution |
|
||||
| seed-0001 | `supabase/seeds/0001_demo_freelancer_os_data.sql` | `docs/database/seed-0001-demo-freelancer-os-data.md` | Optional demo seed, pending execution |
|
||||
|
||||
@@ -23,3 +28,13 @@ This file is the canonical order of SQL files for database setup and migration.
|
||||
Seed files are optional and should live under `supabase/seeds/`.
|
||||
|
||||
They must also be documented and registered in this file, but they should only be run in local/demo environments unless explicitly approved.
|
||||
|
||||
## Applying The Ordered SQL
|
||||
|
||||
Use the migration helper from the repository root:
|
||||
|
||||
```bash
|
||||
DATABASE_URL='postgresql://postgres:password@host:5432/postgres' bash ./scripts/apply-migrations.sh
|
||||
```
|
||||
|
||||
The helper applies `0001` through `0009` in the order listed above. It uses local `psql` when available, otherwise it runs `psql` through Docker.
|
||||
|
||||
+131
-38
@@ -1,57 +1,150 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Neta - Freelancer Operating System Installation Script
|
||||
# Neta - Freelancer Operating System installer
|
||||
|
||||
set -e
|
||||
set -euo pipefail
|
||||
|
||||
echo "🚀 Neta kurulumu başlıyor..."
|
||||
REPO_URL="${NETA_REPO_URL:-https://github.com/poyrazavsever/neta.git}"
|
||||
TARGET_DIR="${NETA_TARGET_DIR:-neta-os}"
|
||||
|
||||
# 1. Check for Git
|
||||
if ! [ -x "$(command -v git)" ]; then
|
||||
echo "Hata: Git yüklü değil. Lütfen önce Git'i kurun." >&2
|
||||
info() {
|
||||
printf "\n%s\n" "$1"
|
||||
}
|
||||
|
||||
fail() {
|
||||
echo "Error: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
require_command() {
|
||||
command -v "$1" >/dev/null 2>&1 || fail "$1 is required."
|
||||
}
|
||||
|
||||
compose_cmd() {
|
||||
if docker compose version >/dev/null 2>&1; then
|
||||
echo "docker compose"
|
||||
elif command -v docker-compose >/dev/null 2>&1; then
|
||||
echo "docker-compose"
|
||||
else
|
||||
fail "Docker Compose is required."
|
||||
fi
|
||||
}
|
||||
|
||||
prompt_required() {
|
||||
local var_name="$1"
|
||||
local label="$2"
|
||||
local current_value="${!var_name:-}"
|
||||
local value
|
||||
|
||||
if [ -n "$current_value" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# 2. Check for Docker
|
||||
if ! [ -x "$(command -v docker)" ]; then
|
||||
echo "Hata: Docker yüklü değil. Lütfen önce Docker'ı kurun." >&2
|
||||
exit 1
|
||||
while true; do
|
||||
read -r -p "$label: " value
|
||||
if [ -n "$value" ]; then
|
||||
printf -v "$var_name" "%s" "$value"
|
||||
export "$var_name"
|
||||
return
|
||||
fi
|
||||
echo "This value is required."
|
||||
done
|
||||
}
|
||||
|
||||
prompt_optional() {
|
||||
local var_name="$1"
|
||||
local label="$2"
|
||||
local default_value="$3"
|
||||
local current_value="${!var_name:-}"
|
||||
local value
|
||||
|
||||
if [ -n "$current_value" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# 3. Target directory
|
||||
TARGET_DIR="neta-os"
|
||||
read -r -p "$label [$default_value]: " value
|
||||
printf -v "$var_name" "%s" "${value:-$default_value}"
|
||||
export "$var_name"
|
||||
}
|
||||
|
||||
prompt_secret_required() {
|
||||
local var_name="$1"
|
||||
local label="$2"
|
||||
local current_value="${!var_name:-}"
|
||||
local value
|
||||
|
||||
if [ -n "$current_value" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
while true; do
|
||||
read -r -s -p "$label: " value
|
||||
echo
|
||||
if [ -n "$value" ]; then
|
||||
printf -v "$var_name" "%s" "$value"
|
||||
export "$var_name"
|
||||
return
|
||||
fi
|
||||
echo "This value is required."
|
||||
done
|
||||
}
|
||||
|
||||
write_env_file() {
|
||||
cat > .env <<EOF
|
||||
NEXT_PUBLIC_SITE_URL=$NEXT_PUBLIC_SITE_URL
|
||||
NETA_PORT=$NETA_PORT
|
||||
NEXT_PUBLIC_SUPABASE_URL=$NEXT_PUBLIC_SUPABASE_URL
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=$NEXT_PUBLIC_SUPABASE_ANON_KEY
|
||||
SUPABASE_SERVICE_ROLE_KEY=$SUPABASE_SERVICE_ROLE_KEY
|
||||
EOF
|
||||
chmod 600 .env || true
|
||||
}
|
||||
|
||||
main() {
|
||||
info "Neta self-host installer"
|
||||
|
||||
require_command git
|
||||
require_command docker
|
||||
docker info >/dev/null 2>&1 || fail "Docker is installed but the daemon is not reachable."
|
||||
|
||||
if [ -d "$TARGET_DIR" ]; then
|
||||
echo "Hata: '$TARGET_DIR' dizini zaten var. Lütfen farklı bir dizinde deneyin veya mevcut dizini silin." >&2
|
||||
exit 1
|
||||
fail "'$TARGET_DIR' already exists. Set NETA_TARGET_DIR or remove the directory."
|
||||
fi
|
||||
|
||||
# 4. Clone repository
|
||||
echo "📦 GitHub'dan kodlar indiriliyor..."
|
||||
git clone https://github.com/poyrazavsever/neta.git "$TARGET_DIR"
|
||||
info "Cloning Neta into $TARGET_DIR"
|
||||
git clone "$REPO_URL" "$TARGET_DIR"
|
||||
cd "$TARGET_DIR"
|
||||
|
||||
# 5. Setup environment variables
|
||||
echo "⚙️ Çevresel değişkenler ayarlanıyor..."
|
||||
if [ -f ".env.example" ]; then
|
||||
cp .env.example .env.local
|
||||
prompt_optional NEXT_PUBLIC_SITE_URL "Public Neta URL" "http://localhost:3000"
|
||||
prompt_optional NETA_PORT "Host port for Neta" "3000"
|
||||
prompt_required NEXT_PUBLIC_SUPABASE_URL "Supabase API URL"
|
||||
prompt_secret_required NEXT_PUBLIC_SUPABASE_ANON_KEY "Supabase anon key"
|
||||
prompt_secret_required SUPABASE_SERVICE_ROLE_KEY "Supabase service role key"
|
||||
|
||||
write_env_file
|
||||
info "Wrote .env"
|
||||
|
||||
read -r -p "Apply Neta database migrations now? Requires a direct Postgres DATABASE_URL. [y/N]: " apply_migrations
|
||||
if [ "$apply_migrations" = "y" ] || [ "$apply_migrations" = "Y" ]; then
|
||||
prompt_secret_required DATABASE_URL "Postgres DATABASE_URL"
|
||||
DATABASE_URL="$DATABASE_URL" bash ./scripts/apply-migrations.sh
|
||||
else
|
||||
echo "Uyarı: .env.example dosyası bulunamadı."
|
||||
echo "Skipping migrations. Run them later with:"
|
||||
echo " DATABASE_URL='postgresql://...' bash ./scripts/apply-migrations.sh"
|
||||
fi
|
||||
|
||||
# 6. Start with Docker Compose
|
||||
echo "🐳 Docker container'ları inşa ediliyor ve başlatılıyor..."
|
||||
if docker compose version > /dev/null 2>&1; then
|
||||
docker compose up -d --build
|
||||
elif docker-compose version > /dev/null 2>&1; then
|
||||
docker-compose up -d --build
|
||||
else
|
||||
echo "Hata: docker-compose komutu bulunamadı." >&2
|
||||
exit 1
|
||||
fi
|
||||
local compose
|
||||
compose="$(compose_cmd)"
|
||||
|
||||
echo ""
|
||||
echo "✅ Kurulum tamamlandı!"
|
||||
echo "Neta başarıyla ayağa kaldırıldı."
|
||||
echo "Tarayıcınızdan http://localhost:3000 adresine giderek Neta'yı kullanmaya başlayabilirsiniz."
|
||||
echo "İlk girişte oluşturacağınız hesap, sistemin tek yöneticisi (admin) olacaktır."
|
||||
info "Validating Docker Compose configuration"
|
||||
$compose config >/dev/null
|
||||
|
||||
info "Building and starting Neta"
|
||||
$compose up -d --build
|
||||
|
||||
info "Neta is starting"
|
||||
echo "Open: $NEXT_PUBLIC_SITE_URL"
|
||||
echo "Create the first admin account at: $NEXT_PUBLIC_SITE_URL/register"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
|
||||
if [ -z "${DATABASE_URL:-}" ]; then
|
||||
echo "DATABASE_URL is required." >&2
|
||||
echo "Example:" >&2
|
||||
echo " DATABASE_URL='postgresql://postgres:password@host:5432/postgres' bash ./scripts/apply-migrations.sh" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SQL_FILES=(
|
||||
"supabase/schema.sql"
|
||||
"supabase/migrations/0002_add_freelancer_os_core_tables.sql"
|
||||
"supabase/migrations/0003_add_project_planning_assets.sql"
|
||||
"supabase/migrations/0004_add_business_os_tables.sql"
|
||||
"supabase/migrations/0005_add_advanced_crm_tables.sql"
|
||||
"supabase/migrations/0006_add_pgvector_and_embeddings.sql"
|
||||
"supabase/migrations/0007_add_client_portal_tables.sql"
|
||||
"supabase/migrations/0008_add_project_progress_and_quota.sql"
|
||||
"supabase/migrations/0009_lock_registration_after_first_admin.sql"
|
||||
)
|
||||
|
||||
run_sql_file() {
|
||||
local file_path="$1"
|
||||
local absolute_path="$ROOT_DIR/$file_path"
|
||||
|
||||
if [ ! -f "$absolute_path" ]; then
|
||||
echo "Missing SQL file: $file_path" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Applying $file_path"
|
||||
|
||||
if command -v psql >/dev/null 2>&1; then
|
||||
psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f "$absolute_path"
|
||||
elif command -v docker >/dev/null 2>&1; then
|
||||
docker run --rm -i postgres:16-alpine \
|
||||
psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -f - < "$absolute_path"
|
||||
else
|
||||
echo "Neither psql nor docker is available to run migrations." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
for sql_file in "${SQL_FILES[@]}"; do
|
||||
run_sql_file "$sql_file"
|
||||
done
|
||||
|
||||
echo "All Neta migrations were applied."
|
||||
+18
-1
@@ -29,4 +29,21 @@ Do not overwrite already executed SQL without also creating a new ordered migrat
|
||||
|
||||
1. `schema.sql`
|
||||
2. `migrations/0002_add_freelancer_os_core_tables.sql`
|
||||
3. Optional: `seeds/0001_demo_freelancer_os_data.sql`
|
||||
3. `migrations/0003_add_project_planning_assets.sql`
|
||||
4. `migrations/0004_add_business_os_tables.sql`
|
||||
5. `migrations/0005_add_advanced_crm_tables.sql`
|
||||
6. `migrations/0006_add_pgvector_and_embeddings.sql`
|
||||
7. `migrations/0007_add_client_portal_tables.sql`
|
||||
8. `migrations/0008_add_project_progress_and_quota.sql`
|
||||
9. `migrations/0009_lock_registration_after_first_admin.sql`
|
||||
10. Optional local/demo data: `seeds/0001_demo_freelancer_os_data.sql`
|
||||
|
||||
## Apply Migrations
|
||||
|
||||
From the repository root:
|
||||
|
||||
```bash
|
||||
DATABASE_URL='postgresql://postgres:password@host:5432/postgres' bash ./scripts/apply-migrations.sh
|
||||
```
|
||||
|
||||
The script applies all required schema files in canonical order. It requires either local `psql` or Docker. If `psql` is not installed, it runs `psql` through the `postgres:16-alpine` Docker image.
|
||||
|
||||
Reference in New Issue
Block a user