-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathdeploy.sh
More file actions
executable file
·116 lines (104 loc) · 4.85 KB
/
Copy pathdeploy.sh
File metadata and controls
executable file
·116 lines (104 loc) · 4.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/env bash
# Resmin — peeka.pics sunucu deploy script'i (Docker'siz, systemd --user).
#
# Atomic release-style deploy (issue #244). Eski script `npm run build`'i
# .next/standalone/ uzerinde in-place yapiyordu; build suresince calisan
# next-server icindeki content-hashed chunk dosyalari yer degistirdigi icin
# ~10-20s'lik build penceresinde her istek ChunkLoadError → 500 aliyordu.
#
# Yeni model:
#
# /home/mirat/apps/resmin/
# ├── deploy.sh
# ├── backend/ # canli backend kaynagi (uv venv burada)
# ├── frontend/ # source — buradan build edilir
# ├── releases/
# │ ├── 20260520-153000/ # her deploy yeni bir release
# │ │ └── frontend/ # .next/standalone + statik kopya
# │ └── 20260520-160000/
# └── current → releases/... # canli release'e symlink (atomic swap)
#
# Eski release'ler 5'i gectikten sonra otomatik siliniyor.
#
# systemd unit gerekliligi:
# resmin-frontend.service'in WorkingDirectory'si /home/mirat/apps/resmin/current/frontend
# olmali. ExecStart 'node server.js' calistirir (Next.js standalone bundle'i).
# Eski unit hala backend/frontend dizinine bagliysa update et:
# [Service]
# WorkingDirectory=/home/mirat/apps/resmin/current/frontend
# ExecStart=/usr/bin/node server.js
#
# Backend tarafi degismedi — ayni dizinde calisiyor.
#
# Rollback: `ln -sfn releases/<onceki> current && systemctl --user restart resmin-frontend`
set -euo pipefail
ROOT="$(cd "$(dirname "$0")" && pwd)"
RELEASES="$ROOT/releases"
CURRENT="$ROOT/current"
KEEP=5
TS="$(date +%Y%m%d-%H%M%S)"
RELEASE="$RELEASES/$TS"
mkdir -p "$RELEASES"
mkdir -p "$RELEASE/frontend"
echo "==> Backend: bagimliliklar + migrate + statik"
cd "$ROOT/backend"
uv sync --frozen --no-dev
set -a; . ./.env; set +a
uv run python manage.py migrate --noinput
uv run python manage.py collectstatic --noinput
# django.contrib.sites defaults to example.com on a fresh DB; notification
# and PM email links are built from it. Keep it pointed at peeka.pics.
uv run python manage.py shell -c "
from django.contrib.sites.models import Site
Site.objects.exclude(pk=1).filter(domain='peeka.pics').delete()
Site.objects.filter(pk=1).update(domain='peeka.pics', name='Peeka')
"
echo "==> API types: backend OpenAPI → frontend/src/lib/api-types.ts"
# Schema değişikliği frontend build'inden önce yansımalı, yoksa npm run build
# eski tipler üzerinde TS hatası verir (pre-commit hook'unun her zaman
# çalışmış olmasına güvenmemek için burada da regen ediyoruz — idempotent).
TMP_OPENAPI="$(mktemp -t peeka-openapi.XXXXXX.json)"
trap 'rm -f "$TMP_OPENAPI"' EXIT
uv run python manage.py dump_openapi 2>/dev/null > "$TMP_OPENAPI"
echo "==> Frontend: $RELEASE/frontend icine build"
cd "$ROOT/frontend"
npm ci
# Otomatik güvenlik yamaları (sadece non-breaking semver-compatible). --force
# kullanmıyoruz çünkü o breaking change'leri de pull eder. Geri kalan (manuel
# bakım gereken) açıkları abort ettirmesin diye `|| true`; çıktı yine deploy
# log'unda görünüyor, ihtiyaç halinde lokalde `npm audit fix --force` ile
# bakılır.
npm audit fix || true
npx --no-install openapi-typescript "$TMP_OPENAPI" -o src/lib/api-types.ts
BACKEND_URL=http://127.0.0.1:8011 npm run build
# Next.js standalone ciktisi statik dosyalari kendi tasimaz. Onceki release
# canli olarak servisi sururken biz tertemiz release dizinine yaziyoruz.
cp -a .next/standalone/. "$RELEASE/frontend/"
# Standalone bundle public/ ve .next/static/'i icine kopyalar ama bu kopyalar
# *bayat* olabilir (Next bunlari standalone'un disinda olusturur, otomatik
# senkronize etmez). Onleri silip disaridaki taze build ciktisiyla degistir —
# eski deploy.sh'taki ayni adim, ama in-place yerine release dizininde.
rm -rf "$RELEASE/frontend/public" "$RELEASE/frontend/.next/static"
cp -a public "$RELEASE/frontend/public"
cp -a .next/static "$RELEASE/frontend/.next/static"
echo "==> Atomic switch: current → $TS"
# ln -sfn = symlink force, no-deref. systemd canli dosya tanitidigini
# yeniden secmiyor → restart sart, ama yeniden yuklenmeyene kadar eski
# release'ten servis vermeye devam ediyor. Pencere = systemd restart.
ln -sfn "$RELEASE" "$CURRENT"
echo "==> Servisleri yeniden baslat"
systemctl --user restart resmin-backend.service
systemctl --user restart resmin-frontend.service
echo "==> Eski release'leri budama (en yeni $KEEP tutuluyor)"
# `tail -n +$((KEEP+1))` ilk KEEP'i atlar, geriye kalanlari siler. Yine de
# current'in isaret ettigi release silinmesin diye `readlink`'i atliyoruz.
LIVE="$(readlink -f "$CURRENT")"
cd "$RELEASES"
ls -1tr | head -n -"$KEEP" | while read -r old; do
if [ "$RELEASES/$old" != "$LIVE" ]; then
echo " pruning $old"
rm -rf "$RELEASES/$old"
fi
done
echo "==> Bitti. Durum:"
systemctl --user --no-pager is-active resmin-minio resmin-backend resmin-frontend