docs: بروزرسانی کامل مستندات — باگها، فیکسها، دیپلوی Production، CI/CD cross-deploy
- payment-gateway.md: سکشن ۸-۱۳ (ZarinPal callback, تخفیف ۱۰۰٪, VAT, ExpirePendingOrders, DeliveryStatus mapping, Production deploy) - CICD-PIPELINE-GUIDE.md: باگ cross-deploy, قالب workflow Production, جدول مقایسه دو محیط - INFRASTRUCTURE-GUIDE.md: سرور Production (45.149.79.127), DB KBS, Proto v0.0.179 - DISCOUNT-STORE-STATUS.md: وضعیت Production Deploy, فلوی پرداخت جدید - SERVER-MIRRORS-CONFIG.md: registries.yaml سرور Production - INDEX.md: تاریخ, توضیحات بروز, لینکهای سریع جدید
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# 🔧 راهنمای CI/CD Pipeline — Gitea Actions + K3s
|
||||
|
||||
> آخرین بروزرسانی: February 11, 2026
|
||||
> آخرین بروزرسانی: February 17, 2026
|
||||
|
||||
---
|
||||
|
||||
@@ -230,6 +230,110 @@ DOCKER_BUILDKIT=0 docker build --network host -t ... .
|
||||
|
||||
---
|
||||
|
||||
### مشکل ۸: `COPY libs/` fails in Docker build (BackOffice)
|
||||
|
||||
**خطا:**
|
||||
```
|
||||
COPY failed: file not found in build context: stat libs/: file does not exist
|
||||
```
|
||||
|
||||
**علت:** Dockerfile خط `COPY ["libs/", "libs/"]` داشت ولی `libs/` خارج از Docker build context (`src/`) بود. قبلاً BFF DLLها استفاده میشدن، ولی حالا از NuGet package مستقیم استفاده میشه.
|
||||
|
||||
**راهحل:**
|
||||
1. حذف `COPY ["libs/", "libs/"]` از Dockerfile
|
||||
2. تغییر `ProjectReference` به `PackageReference` در csproj:
|
||||
```xml
|
||||
<!-- قبل -->
|
||||
<ProjectReference Include="../../../CMS/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj" />
|
||||
<!-- بعد -->
|
||||
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.178" />
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### مشکل ۹: ProjectReference خارج از Docker context (FrontOffice/BackOffice)
|
||||
|
||||
**خطا:**
|
||||
```
|
||||
error CS0246: The type or namespace name 'CustomerAddressModel' could not be found
|
||||
```
|
||||
|
||||
**علت:** csproj از `ProjectReference Include="../../../CMS/src/CMSMicroservice.Protobuf/..."` استفاده میکرد. در Docker build context فقط `src/` موجوده → CMS قابل دسترسی نیست.
|
||||
|
||||
**راهحل:**
|
||||
1. بامپ نسخه پروتوباف (`0.0.177` → `0.0.178`)
|
||||
2. `dotnet pack -c Release` و push به Nexus
|
||||
3. تغییر هر دو پروژه (FrontOffice + BackOffice) به `PackageReference`
|
||||
|
||||
```bash
|
||||
# Pack & Push
|
||||
cd CMS/src/CMSMicroservice.Protobuf
|
||||
dotnet pack -c Release
|
||||
dotnet nuget push bin/Release/Foursat.CMSMicroservice.Protobuf.0.0.178.nupkg \
|
||||
--source http://194.5.195.53:32081/repository/foursat-nuget-hosted/index.json \
|
||||
--api-key admin:87zH26nbqT --skip-duplicate
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### مشکل ۱۰: `nginx:alpine` TLS handshake timeout
|
||||
|
||||
**خطا:**
|
||||
```
|
||||
Get "https://registry-1.docker.io/v2/": net/http: TLS handshake timeout
|
||||
```
|
||||
|
||||
**علت:** Dockerfile خط `FROM nginx:alpine` مستقیم از Docker Hub پول میکرد ولی سرور به Docker Hub دسترسی نداره.
|
||||
|
||||
**راهحل:** تغییر به رجیستری لوکال:
|
||||
```dockerfile
|
||||
# قبل
|
||||
FROM nginx:alpine AS final
|
||||
# بعد
|
||||
FROM 194.5.195.53:32082/nginx:alpine AS final
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### مشکل ۱۱: SERVER_PASSWORD secret missing → Permission denied
|
||||
|
||||
**خطا:**
|
||||
```
|
||||
Permission denied, please try again.
|
||||
```
|
||||
|
||||
**علت:** سکرت `SERVER_PASSWORD` در ریپو Gitea تنظیم نشده بود. Pipeline از `sshpass -e` با `${{ secrets.SERVER_PASSWORD }}` برای SSH استفاده میکنه.
|
||||
|
||||
**راهحل:** اضافه کردن سکرت از طریق Gitea API:
|
||||
```bash
|
||||
curl -sk -u "admin:87zH26nbqT" -X PUT \
|
||||
"https://git.se.kbs1.ir/api/v1/repos/admin/BackOffice/actions/secrets/SERVER_PASSWORD" \
|
||||
-H "Content-Type: application/json" -d '{"data":"87zH26nbqT"}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### مشکل ۱۲: CMS ingress 502 — backend-protocol: GRPC
|
||||
|
||||
**خطا:** `https://cms.se.kbs1.ir/` → 502 Bad Gateway
|
||||
|
||||
**علت:** CMS ingress annotation `backend-protocol: GRPC` داشت + Kestrel فقط `Http2`. مرورگر HTTP/1.1 میفرسته → nginx نمیتونه به gRPC backend فوروارد کنه.
|
||||
|
||||
**راهحل (دو تغییر):**
|
||||
1. Kestrel protocol → `Http1AndHttp2` (هم gRPC هم REST):
|
||||
```bash
|
||||
kubectl set env deployment/cms Kestrel__EndpointDefaults__Protocols=Http1AndHttp2
|
||||
```
|
||||
2. حذف GRPC annotations از ingress:
|
||||
```bash
|
||||
kubectl annotate ingress cms-ingress nginx.ingress.kubernetes.io/backend-protocol-
|
||||
kubectl annotate ingress cms-ingress nginx.ingress.kubernetes.io/grpc-backend-
|
||||
```
|
||||
|
||||
> ⚠️ FrontOffice از gRPC-Web استفاده میکنه که روی HTTP/1.1 هم کار میکنه.
|
||||
|
||||
---
|
||||
|
||||
## 🔄 تغییرات prod-deploy (قدیم → جدید)
|
||||
|
||||
| مورد | قدیم (prod-deploy) | جدید |
|
||||
@@ -290,7 +394,15 @@ ubuntu-22.04 → docker://docker.gitea.com/runner-images:ubuntu-22.04
|
||||
| Secret | استفاده |
|
||||
|--------|---------|
|
||||
| `REGISTRY_PASSWORD` | پسورد Docker registry (admin) |
|
||||
| `SERVER_PASSWORD` | پسورد SSH سرور (root) |
|
||||
| `SERVER_PASSWORD` | پسورد SSH سرور (root) — ⚠️ باید در هر ۳ ریپو ست بشه |
|
||||
|
||||
> **نکته:** اگر `SERVER_PASSWORD` ست نباشه، مرحله Deploy با `Permission denied` فیل میشه.
|
||||
> با API اضافه کنید:
|
||||
> ```bash
|
||||
> curl -sk -u "admin:PASSWORD" -X PUT \
|
||||
> "https://git.se.kbs1.ir/api/v1/repos/admin/REPO/actions/secrets/SERVER_PASSWORD" \
|
||||
> -H "Content-Type: application/json" -d '{"data":"PASSWORD"}'
|
||||
> ```
|
||||
|
||||
---
|
||||
|
||||
@@ -416,3 +528,89 @@ jobs:
|
||||
kubectl rollout status deployment/<service> --timeout=180s
|
||||
"
|
||||
```
|
||||
---
|
||||
|
||||
## 🐛 باگ بحرانی: Cross-Deployment — Push به Production ریدیپلوی Staging (اسفند ۱۴۰۴)
|
||||
|
||||
### علائم:
|
||||
- Push به برنچ `production` → هم production و هم staging ریدیپلوی شدند
|
||||
- CMS staging pod بعد از push ریستارت شد
|
||||
- Runner log: **۲ تسک CMS** بجای ۱ تسک اجرا شد
|
||||
|
||||
### علت ریشهای:
|
||||
Gitea Act Runner **تمام فایلهای workflow** داخل `.gitea/workflows/` برنچ push شده رو اجرا میکنه — حتی اگه `on.push.branches` برنچ دیگهای باشه. وقتی production push شد، `kub-deploy.yml` (trigger: `kub-stage`) هم اجرا شد و ایمیج `admin/cms:latest` رو با کد production ساخت → staging از `latest` pull کرد → **staging با DB production بالا اومد!**
|
||||
|
||||
### راهحل:
|
||||
حذف workflowهای staging از برنچ production (هر ۳ ریپو):
|
||||
```bash
|
||||
git rm .gitea/workflows/kub-deploy.yml .gitea/workflows/cms-stage.yml # CMS
|
||||
git rm .gitea/workflows/fo-stage.yml .gitea/workflows/kub-deploy.yml # FrontOffice
|
||||
git rm .gitea/workflows/bo-stage.yml .gitea/workflows/kub-deploy.yml # BackOffice
|
||||
```
|
||||
|
||||
> ⚠️ **قانون طلایی:** هر برنچ فقط workflow مربوط به خودش رو داشته باشه.
|
||||
|
||||
---
|
||||
|
||||
## 🐛 مشکل ۱۳: Production deploy ایمیج pull نمیشد
|
||||
|
||||
**علت:** Production K8s از `git.foursat.afrino.co/admin/cms:prod` pull میکرد، ولی CI ایمیج رو به `194.5.195.53:30080` push میکرد.
|
||||
|
||||
**راهحل:**
|
||||
1. اضافه کردن `194.5.195.53:30080` به `/etc/rancher/k3s/registries.yaml` پروداکشن + ریاستارت K3s
|
||||
2. آپدیت deployment image: `kubectl set image deployment/cms cms=194.5.195.53:30080/admin/cms:prod`
|
||||
3. فیکس `prod-deploy.yml`: `K8S_SSH_PASSWORD` → `SERVER_PASSWORD`, `rollout restart` → `set image :sha`
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Production Workflow Template (فعلی)
|
||||
|
||||
```yaml
|
||||
name: Build and Deploy to Production
|
||||
on:
|
||||
push:
|
||||
branches: [production]
|
||||
env:
|
||||
REGISTRY: 194.5.195.53:30080
|
||||
IMAGE_NAME: admin/<service>
|
||||
K8S_SERVER: 45.149.79.127
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: 194.5.195.53:32082/docker-sshpass:latest
|
||||
options: --privileged
|
||||
steps:
|
||||
# ... (Start Docker, Checkout, Login — مشابه staging)
|
||||
- name: Build Docker Image
|
||||
run: |
|
||||
DOCKER_BUILDKIT=0 docker build --network host \
|
||||
-t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
|
||||
-t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:prod .
|
||||
- name: Push to Registry
|
||||
run: |
|
||||
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
|
||||
docker push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:prod
|
||||
- name: Deploy to Production
|
||||
run: |
|
||||
export SSHPASS="${{ secrets.SERVER_PASSWORD }}"
|
||||
sshpass -e ssh -o StrictHostKeyChecking=no root@${{ env.K8S_SERVER }} "
|
||||
kubectl set image deployment/<svc> <svc>=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
|
||||
kubectl rollout status deployment/<svc> --timeout=300s
|
||||
"
|
||||
```
|
||||
|
||||
> تفاوت staging vs production: staging = tag `latest` + `rollout restart` | production = tag `sha` + `set image`
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ مشخصات دو محیط
|
||||
|
||||
| | Staging | Production |
|
||||
|--|---------|------------|
|
||||
| **سرور** | `194.5.195.53` | `45.149.79.127` |
|
||||
| **DB** | `mssql-svc@Foursat` | `45.149.79.127,31433@KBS` |
|
||||
| **Registry** | `194.5.195.53:30080` (local) | همان staging registry |
|
||||
| **Image Tags** | `:latest` | `:prod` + `:sha` |
|
||||
| **Branch** | `kub-stage` | `production` |
|
||||
| **Domains** | `*.se.kbs1.ir` | `*.kbs1.ir` |
|
||||
@@ -2,12 +2,23 @@
|
||||
|
||||
## 📌 Server Information
|
||||
|
||||
### سرور Staging
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Server IP | `194.5.195.53` |
|
||||
| SSH Access | `root / 87zH26nbqT` |
|
||||
| Kubernetes | K3s with local-path storage |
|
||||
| ServiceLB | K3s svclb (built-in) |
|
||||
| Domains | `*.se.kbs1.ir` |
|
||||
|
||||
### سرور Production
|
||||
| Item | Value |
|
||||
|------|-------|
|
||||
| Server IP | `45.149.79.127` |
|
||||
| SSH Access | `root / 87zH26nbqT` |
|
||||
| Kubernetes | K3s with local-path storage |
|
||||
| ServiceLB | K3s svclb (built-in) |
|
||||
| Domains | `*.kbs1.ir` |
|
||||
|
||||
---
|
||||
|
||||
@@ -22,13 +33,22 @@
|
||||
| PVC | `mssql-pvc` (10Gi) |
|
||||
|
||||
### Databases:
|
||||
|
||||
#### Staging (194.5.195.53):
|
||||
- `gitea` - Gitea metadata
|
||||
- `Foursat` - Application database
|
||||
- `Foursat` - Application database (staging)
|
||||
- `Hosein` - Application database
|
||||
|
||||
### Connection String:
|
||||
#### Production (45.149.79.127):
|
||||
- `KBS` - Application database (production)
|
||||
|
||||
### Connection Strings:
|
||||
```
|
||||
# Staging
|
||||
Server=mssql-svc,1433;Database=Foursat;User Id=sa;Password=87zH26nbqT;TrustServerCertificate=true
|
||||
|
||||
# Production (env override)
|
||||
Server=45.149.79.127,31433;Database=KBS;User Id=sa;Password=YourStrong@Passw0rd;TrustServerCertificate=true
|
||||
```
|
||||
|
||||
---
|
||||
@@ -170,11 +190,13 @@ kubectl logs -f deploy/nexus
|
||||
|
||||
## 🔐 Credentials Summary
|
||||
|
||||
| Service | Username | Password |
|
||||
|---------|----------|----------|
|
||||
| Server SSH | root | 87zH26nbqT |
|
||||
| MSSQL | sa | 87zH26nbqT |
|
||||
| Gitea | admin | (set during install) |
|
||||
| Service | Username | Password | Server |
|
||||
|---------|----------|----------|--------|
|
||||
| Staging SSH | root | 87zH26nbqT | 194.5.195.53 |
|
||||
| Production SSH | root | 87zH26nbqT | 45.149.79.127 |
|
||||
| Staging MSSQL | sa | 87zH26nbqT | mssql-svc:1433 |
|
||||
| Production MSSQL | sa | YourStrong@Passw0rd | 45.149.79.127:31433 |
|
||||
| Gitea | admin | (set during install) | 194.5.195.53 |
|
||||
|
||||
---
|
||||
|
||||
@@ -218,7 +240,42 @@ curl -s http://194.5.195.53:32082/v2/_catalog
|
||||
|
||||
---
|
||||
|
||||
*Last Updated: 2025-01-18*
|
||||
---
|
||||
|
||||
## 🔧 CMS Ingress & Kestrel Protocol (بروزشده: February 2026)
|
||||
|
||||
### تنظیمات Kestrel:
|
||||
| متغیر | مقدار قبلی | مقدار فعلی |
|
||||
|--------|-----------|------------|
|
||||
| `Kestrel__EndpointDefaults__Protocols` | `Http2` | `Http1AndHttp2` |
|
||||
|
||||
> با `Http1AndHttp2` هم gRPC (HTTP/2) و هم REST/HTTP (HTTP/1.1) روی یک پورت کار میکنن.
|
||||
|
||||
### تنظیمات Ingress CMS:
|
||||
| Annotation | مقدار قبلی | مقدار فعلی |
|
||||
|-----------|-----------|------------|
|
||||
| `backend-protocol` | `GRPC` | حذف شد |
|
||||
| `grpc-backend` | `true` | حذف شد |
|
||||
| `ssl-redirect` | `true` | `true` |
|
||||
| `cert-manager.io/cluster-issuer` | `letsencrypt-prod` | `letsencrypt-prod` |
|
||||
|
||||
> ⚠️ FrontOffice از gRPC-Web استفاده میکنه که روی HTTP/1.1 هم کار میکنه — نیازی به annotation GRPC نیست.
|
||||
|
||||
### NuGet Package (Proto):
|
||||
| پکیج | نسخه | رجیستری |
|
||||
|-------|-------|--------|
|
||||
| `Foursat.CMSMicroservice.Protobuf` | `0.0.179` | Nexus (`foursat-nuget-hosted`) |
|
||||
|
||||
### Gitea Secrets (هر ۳ ریپو):
|
||||
| Secret | CMS | FrontOffice | BackOffice |
|
||||
|--------|-----|-------------|------------|
|
||||
| `REGISTRY_PASSWORD` | ✅ | ✅ | ✅ |
|
||||
| `SERVER_PASSWORD` | ✅ | ✅ | ✅ |
|
||||
| `KUBECONFIG` | ✅ | ✅ | ✅ |
|
||||
|
||||
---
|
||||
|
||||
*Last Updated: February 17, 2026*
|
||||
|
||||
|
||||
---
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
# Server Mirrors Configuration
|
||||
|
||||
**Server:** 194.5.195.53
|
||||
**Date:** 2026-01-29
|
||||
**Staging Server:** 194.5.195.53
|
||||
**Production Server:** 45.149.79.127
|
||||
**Date:** 2026-02-17
|
||||
|
||||
---
|
||||
|
||||
## 1. Docker Registry Mirrors (K3s)
|
||||
|
||||
فایل: `/etc/rancher/k3s/registries.yaml`
|
||||
### Staging — `/etc/rancher/k3s/registries.yaml` (194.5.195.53)
|
||||
|
||||
### ترتیب Pull کردن ایمیجها:
|
||||
1. **Nexus** (194.5.195.53:32082) - لوکال
|
||||
@@ -66,6 +67,55 @@ configs:
|
||||
systemctl restart k3s
|
||||
```
|
||||
|
||||
### Production — `/etc/rancher/k3s/registries.yaml` (45.149.79.127)
|
||||
|
||||
Production server از staging registry ها pull میکنه:
|
||||
|
||||
```yaml
|
||||
mirrors:
|
||||
"docker.io":
|
||||
endpoint:
|
||||
- "http://194.5.195.53:32082"
|
||||
- "https://docker.arvancloud.ir"
|
||||
- "https://registry-1.docker.io"
|
||||
"194.5.195.53:32082":
|
||||
endpoint:
|
||||
- "http://194.5.195.53:32082"
|
||||
"194.5.195.53:30080":
|
||||
endpoint:
|
||||
- "http://194.5.195.53:30080"
|
||||
"git.foursat.afrino.co":
|
||||
endpoint:
|
||||
- "https://git.foursat.afrino.co"
|
||||
"git.se.kbs1.ir":
|
||||
endpoint:
|
||||
- "https://git.se.kbs1.ir"
|
||||
|
||||
configs:
|
||||
"194.5.195.53:32082":
|
||||
auth:
|
||||
username: admin
|
||||
password: 87zH26nbqT
|
||||
"194.5.195.53:30080":
|
||||
auth:
|
||||
username: admin
|
||||
password: 87zH26nbqT
|
||||
"git.foursat.afrino.co":
|
||||
auth:
|
||||
username: admin
|
||||
password: 87zH26nbqT
|
||||
tls:
|
||||
insecure_skip_verify: true
|
||||
"git.se.kbs1.ir":
|
||||
auth:
|
||||
username: admin
|
||||
password: 87zH26nbqT
|
||||
tls:
|
||||
insecure_skip_verify: true
|
||||
```
|
||||
|
||||
> ⚠️ Production از `194.5.195.53:30080` (Gitea container registry) برای pull ایمیجهای CI/CD استفاده میکنه.
|
||||
|
||||
---
|
||||
|
||||
## 2. APT Package Mirrors (Ubuntu 24.04 Noble)
|
||||
|
||||
Reference in New Issue
Block a user