seed script

This commit is contained in:
javad committed 2026-09-10 16:39:02 +03:30
1 parent fa9d154db9
commit 08c30aa47f
15 files changed
+496 -17

No files matched your search

+11 -13
View File
@@ -10,14 +10,15 @@ PostgreSQL جزو این Compose نیست و از دیتابیس مدیریت‌
## 1. Volumeهای Coolify
پیش از اولین deploy دو Docker volume با همین نام‌ها ایجاد کنید:
پیش از اولین deploy سه Docker volume با همین نام‌ها ایجاد کنید:
```text
customer_ticket_static
customer_ticket_media
customer_ticket_seed
```
در صورت انتخاب نام دیگر، متغیرهای `STATIC_VOLUME_NAME` و `MEDIA_VOLUME_NAME` را مطابق آن تنظیم کنید. media حاوی آپلودهای ماندگار است. static در هر startup دوباره با `collectstatic` تکمیل می‌شود اما برای اشتراک بین web و Nginx volume لازم دارد.
در صورت انتخاب نام دیگر، متغیرهای `STATIC_VOLUME_NAME`، `MEDIA_VOLUME_NAME` و `SEED_VOLUME_NAME` را مطابق آن تنظیم کنید. media حاوی آپلودهای ماندگار است. static در هر startup دوباره با `collectstatic` تکمیل می‌شود اما برای اشتراک بین web و Nginx volume لازم دارد. سه فایل تولیدشده در `production-seed/` باید پیش از اولین startup داخل ریشه volume سوم قرار گیرند.
## 2. دامنه‌ها و Traefik خود Coolify
@@ -47,7 +48,9 @@ DATABASE_WAIT_TIMEOUT=60
STATIC_VOLUME_NAME=customer_ticket_static
MEDIA_VOLUME_NAME=customer_ticket_media
SEED_VOLUME_NAME=customer_ticket_seed
MEDIA_SIGNING_SECRET=<separate-random-secret-at-least-32-characters>
REQUIRE_PRODUCTION_SEED=1
```
نام دیتابیس انتهای URL باید نام واقعی دیتابیس باشد. اگر دیتابیس ساخته‌شده `customerTicket` است، URL باید به `/customerTicket` ختم شود؛ URLی که به `/postgres` ختم می‌شود به دیتابیس پیش‌فرض `postgres` متصل خواهد شد. اگر password شامل `@`، `:`، `/`، `#` یا `%` است آن را URL-encode کنید.
@@ -115,17 +118,12 @@ SECURE_HSTS_PRELOAD=false
## 7. ترتیب اولین deploy
1. volumeها و database خالی را ایجاد کنید.
2. Environment Variables را در Coolify وارد کنید.
3. Compose را deploy، دامنه اصلی را به `web:8000` و pathهای static/media گفته‌شده را به `nginx:80` متصل کنید.
4. log سرویس `web` را برای موفقیت migrate، bootstrap، collectstatic و Gunicorn بررسی کنید.
5. log سرویس `notification-worker` را بررسی کنید؛ container باید Running بماند.
6. یک‌بار superuser بسازید:
```bash
docker compose exec web python manage.py createsuperuser
```
7. در پنل مدیریت، SMS templateها و `NotificationPolicy`ها را بررسی کنید و با گیرنده آزمایشی مجاز یک SMS و یک پیام Bale واقعی بفرستید.
2. طبق `docs/PRODUCTION_SEED.md` سه فایل seed را داخل volume `customer_ticket_seed` قرار دهید.
3. Environment Variables را در Coolify وارد کنید.
4. Compose را deploy، دامنه اصلی را به `web:8000` و pathهای static/media گفته‌شده را به `nginx:80` متصل کنید.
5. log سرویس `web` را برای موفقیت migrate، import production seed، collectstatic و Gunicorn بررسی کنید. وقتی seed موجود است، bootstrap عمداً اجرا نمی‌شود تا snapshot تغییر نکند.
6. log سرویس `notification-worker` را بررسی کنید؛ container باید Running بماند.
7. با superuser منتقل‌شده از SQLite وارد شوید و با گیرنده آزمایشی مجاز یک SMS و یک پیام Bale واقعی بفرستید.
## 8. کنترل سلامت و عیب‌یابی
+79
View File
@@ -0,0 +1,79 @@
# انتقال خودکار SQLite به PostgreSQL Production
این فرایند تمام داده‌های پایدار فعلی را منتقل می‌کند:
- کاربران، hash رمزهای قابل استفاده، superuser، گروه‌ها و permissionها
- واحدهای سازمانی، عضویت‌ها، نقش‌ها و پروفایل پرسنل
- مشتریان، گروه مخاطبان، دسته‌بندی‌ها و SLA
- branding، عنوان صفحات، SMS templateها، NotificationPolicy و سیاست فایل‌ها
- تیکت‌ها، ارسال‌های گروهی، رویدادها، پیام‌ها، رسیدهای خواندن و attachmentها
- تمام فایل‌های موجود در `MEDIA_ROOT`، شامل branding، avatar و فایل تیکت
داده‌های موقتی و خطرناک زیر عمداً منتقل نمی‌شوند: sessionها، OTPهای قبلی، Magic Linkهای قبلی، admin log و `NotificationJob`. انتقال outbox قبلی می‌توانست بعد از بالا آمدن worker باعث ارسال مجدد SMS یا Bale شود.
## خروجی ساخته‌شده
دستور زیر از SQLite فعلی snapshot می‌گیرد:
```powershell
.\.venv\Scripts\python.exe manage.py export_production_seed --output production-seed --force
```
برای وضعیت فعلی پروژه خروجی قبلاً تولید شده و شامل ۳۹۵ رکورد پایدار و ۵۷ فایل media است:
```text
production-seed/
data.json.gz
media.tar.gz
manifest.json
```
این پوشه شامل اطلاعات شخصی و password hash است و عمداً توسط Git و Docker ignore می‌شود. آن را commit، ایمیل یا در فضای عمومی بارگذاری نکنید.
## انتقال امن به volume سرور
در Coolify volume خارجی `customer_ticket_seed` را ایجاد کنید. سه فایل بالا باید مستقیماً در ریشه آن قرار بگیرند، به شکلی که container مسیر زیر را ببیند:
```text
/app/production-seed/manifest.json
/app/production-seed/data.json.gz
/app/production-seed/media.tar.gz
```
فایل‌ها را با قابلیت Persistent Storage/File Mount خود Coolify یا یک انتقال امن مانند SCP به سرور ببرید. اگر روی سرور در `/tmp/customer-ticket-seed` قرار گرفته‌اند، مدیر سرور می‌تواند volume را این‌گونه پر کند:
```bash
docker run --rm \
-v customer_ticket_seed:/target \
-v /tmp/customer-ticket-seed:/source:ro \
alpine:3.20 sh -c 'cp /source/data.json.gz /source/media.tar.gz /source/manifest.json /target/'
```
پس از کپی، نسخه موجود در `/tmp` را امن حذف کنید. volume seed در Compose فقط read-only داخل web mount می‌شود.
## اجرای خودکار
در اولین startup سرویس web ترتیب زیر اجرا می‌شود:
1. انتظار برای PostgreSQL
2. اجرای migrationها
3. اعتبارسنجی SHA-256 فایل‌های seed
4. اطمینان از خالی بودن PostgreSQL و media volume
5. حذف defaultهای data migration و import کامل snapshot
6. انتقال media به volume اصلی
7. ثبت `ProductionSeedState`
8. رد کردن `bootstrap` برای حفظ دقیق snapshot به‌عنوان منبع authoritative
9. اجرای `collectstatic` و Gunicorn
در deployهای بعدی checksum قبلاً ثبت‌شده تشخیص داده می‌شود و import دوباره انجام نمی‌شود. اگر bundle نباشد، با `REQUIRE_PRODUCTION_SEED=1` سرویس عمداً متوقف می‌شود تا production ناقص بالا نیاید.
## محدودیت‌های ایمنی
- import فقط روی PostgreSQL اجرا می‌شود.
- دیتابیس دارای User یا seed قبلی با checksum متفاوت پذیرفته نمی‌شود.
- media volume غیرخالی overwrite نمی‌شود.
- مسیرهای مشکوک، symlink و path traversal در archive رد می‌شوند.
- checksum هر دو فایل پیش از هر تغییر بررسی می‌شود.
- شکست import باعث rollback دیتابیس و حذف فایل‌های کپی‌شده همان اجرا می‌شود.
اگر واقعاً می‌خواهید production بدون snapshot بالا بیاید، `REQUIRE_PRODUCTION_SEED=0` بگذارید؛ در این حالت فقط bootstrap استاندارد اجرا می‌شود و کاربران دارای password فعلی SQLite منتقل نخواهند شد.