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:
masoodafar-web
2026-02-17 01:44:05 +03:30
parent ad31c8be97
commit 4ef4bfbeef
6 changed files with 632 additions and 32 deletions
+200 -2
View File
@@ -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` |