Files
furkanyigit34 eb679300f3 ci(k8s): Gitea K8s pipeline ekle — CiroMarket K8s migration
Ne yaptık:
- .gitea/workflows/deploy-backend.yaml — Gitea Actions ile backend image'ı build et, Gitea registry'e push et, ci-cd repo manifest'ini bump'la
- .gitea/workflows/deploy-frontend.yaml — Frontend'i VITE_API_URL=https://trendyol-api.194.187.253.61.sslip.io ile build et, aynı pattern
- .github/workflows/deploy.yml — sync-gitea job eklendi: GitHub push sonrası Gitea mirror sync + deploy-backend/frontend.yaml dispatch

Neden yaptık:
- CiroMarket'i Coolify'dan K8s'e taşıma projesi
- Coolify pipeline parallel çalışmaya devam ediyor (zero downtime)
- GitHub push → Gitea mirror → Gitea Actions → Gitea registry → ArgoCD → K8s rolling update zinciri tamamlandı
2026-05-18 11:42:02 +03:00

369 lines
16 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Deploy
# ─────────────────────────────────────────────────────────────────────────────
# Zincir: validate → build-push (backend+frontend) → deploy → verify
# Trendyol-analiz tertemiz auto-deploy — SellerX deploy-frontend.yml pattern'i
# ─────────────────────────────────────────────────────────────────────────────
# K8s pipeline (Gitea mirror → Gitea Actions → Gitea registry → ArgoCD) parallel
# çalışır — Coolify pipeline'ı DURDURMAZ.
# ─────────────────────────────────────────────────────────────────────────────
on:
push:
branches: [main]
workflow_dispatch:
env:
REGISTRY: ghcr.io
BACKEND_IMAGE: ${{ github.repository }}/backend
FRONTEND_IMAGE: ${{ github.repository }}/frontend
PYTHON_VERSION: '3.13'
NODE_VERSION: '20'
jobs:
# ───────────────────────────────────────────────────────────────────────────
# K8s MIRROR SYNC — Coolify pipeline'dan BAĞIMSIZ, validate ile PARALEL.
# GitHub push → Gitea mirror sync → Gitea Actions → Gitea registry → ArgoCD
# Başarısız olursa Coolify pipeline DURMUYOR.
# ───────────────────────────────────────────────────────────────────────────
sync-gitea:
name: Sync Gitea Mirror (K8s Pipeline)
runs-on: ubuntu-latest
steps:
- name: Trigger Gitea mirror sync
run: |
HTTP=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST "https://git.novasis.tr/api/v1/repos/admin/trendyol-analiz/mirror-sync" \
-H "Authorization: token ${{ secrets.GITEA_MIRROR_TOKEN }}")
echo "Mirror sync HTTP: $HTTP"
if [ "$HTTP" -ge 400 ]; then
echo "Mirror sync failed (HTTP $HTTP) — K8s pipeline delayed, Coolify unaffected"
exit 0
fi
echo "Mirror sync triggered — waiting 30s for sync to complete..."
sleep 30
- name: Dispatch Gitea Actions build (deploy-backend.yaml)
run: |
HTTP=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST "https://git.novasis.tr/api/v1/repos/admin/trendyol-analiz/actions/workflows/deploy-backend.yaml/dispatches" \
-H "Authorization: token ${{ secrets.GITEA_MIRROR_TOKEN }}" \
-H "Content-Type: application/json" \
-d '{"ref":"main"}')
echo "Gitea backend dispatch HTTP: $HTTP"
if [ "$HTTP" -ge 400 ]; then
echo "Gitea backend dispatch failed — trigger manually"
fi
- name: Dispatch Gitea Actions build (deploy-frontend.yaml)
run: |
HTTP=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST "https://git.novasis.tr/api/v1/repos/admin/trendyol-analiz/actions/workflows/deploy-frontend.yaml/dispatches" \
-H "Authorization: token ${{ secrets.GITEA_MIRROR_TOKEN }}" \
-H "Content-Type: application/json" \
-d '{"ref":"main"}')
echo "Gitea frontend dispatch HTTP: $HTTP"
if [ "$HTTP" -ge 400 ]; then
echo "Gitea frontend dispatch failed — trigger manually"
fi
# ───────────────────────────────────────────────────────────────────────────
# ADIM 1a — Backend hızlı sağlık testi (pytest)
# ───────────────────────────────────────────────────────────────────────────
validate-backend:
name: 🐍 Backend Test
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15-alpine
env:
POSTGRES_DB: trendyol_db
POSTGRES_USER: postgres
POSTGRES_PASSWORD: testpassword
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
defaults:
run:
working-directory: backend
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
cache-dependency-path: backend/requirements.txt
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-asyncio httpx || true
- name: Run tests
run: pytest -q || echo "No tests / skipped"
env:
DATABASE_URL: postgresql://postgres:testpassword@localhost:5432/trendyol_db
# ───────────────────────────────────────────────────────────────────────────
# ADIM 1b — Frontend lint + build (Vite)
# ───────────────────────────────────────────────────────────────────────────
validate-frontend:
name: ⚛️ Frontend Lint & Build
runs-on: ubuntu-latest
defaults:
run:
working-directory: admin-panel
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
cache-dependency-path: admin-panel/package-lock.json
- run: npm ci
- run: npm run lint || true
- name: Production build
run: npm run build
env:
VITE_API_URL: https://trendyol-api.194.187.253.230.sslip.io
# ───────────────────────────────────────────────────────────────────────────
# ADIM 2a — Backend image build & push (GHCR)
# ───────────────────────────────────────────────────────────────────────────
build-push-backend:
name: 🐳 Build & Push Backend
needs: [validate-backend, validate-frontend]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE }}
tags: |
type=sha,prefix=
type=raw,value=latest
- uses: docker/build-push-action@v5
with:
context: .
file: backend/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=backend
cache-to: type=gha,mode=max,scope=backend
# ───────────────────────────────────────────────────────────────────────────
# ADIM 2b — Frontend image build & push (GHCR)
# ───────────────────────────────────────────────────────────────────────────
build-push-frontend:
name: 🐳 Build & Push Frontend
needs: [validate-backend, validate-frontend]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE }}
tags: |
type=sha,prefix=
type=raw,value=latest
- uses: docker/build-push-action@v5
with:
context: ./admin-panel
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
VITE_API_URL=https://trendyol-api.194.187.253.230.sslip.io
cache-from: type=gha,scope=frontend
cache-to: type=gha,mode=max,scope=frontend
# ───────────────────────────────────────────────────────────────────────────
# ADIM 3 — Coolify deploy webhook
# Deployment UUID'yi output'a yaz → verify job bu spesifik deploy'u izleyecek
# ───────────────────────────────────────────────────────────────────────────
deploy:
name: 🚀 Deploy to Coolify
needs: [build-push-backend, build-push-frontend]
runs-on: ubuntu-latest
outputs:
deployment_uuid: ${{ steps.trigger.outputs.deployment_uuid }}
steps:
- name: Trigger Coolify deploy
id: trigger
run: |
response=$(curl -s -w "\n%{http_code}" \
-X POST "${{ secrets.COOLIFY_BASE_URL }}/api/v1/deploy?uuid=${{ secrets.COOLIFY_TRENDYOL_UUID }}&force=true" \
-H "Authorization: Bearer ${{ secrets.COOLIFY_API_TOKEN }}")
http_code=$(echo "$response" | tail -1)
body=$(echo "$response" | head -n -1)
echo "Response: $body (HTTP $http_code)"
if [ "$http_code" -ge 400 ]; then
echo "❌ Coolify deploy trigger failed!"
exit 1
fi
# Deployment UUID'yi parse et
DEPLOY_UUID=$(echo "$body" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d['deployments'][0]['deployment_uuid'])")
echo "deployment_uuid=$DEPLOY_UUID" >> "$GITHUB_OUTPUT"
echo "✅ Coolify deploy queued — deployment_uuid: $DEPLOY_UUID"
# ───────────────────────────────────────────────────────────────────────────
# ADIM 4 — Verify deployment
# Spesifik deployment_uuid'yi poll et: queued → in_progress → finished/failed
# ───────────────────────────────────────────────────────────────────────────
verify:
name: ✅ Verify Deployment
needs: deploy
runs-on: ubuntu-latest
steps:
- name: Coolify deployment status polling
run: |
DEPLOY_UUID="${{ needs.deploy.outputs.deployment_uuid }}"
DEPLOY_URL="${{ secrets.COOLIFY_BASE_URL }}/api/v1/deployments/$DEPLOY_UUID"
MAX=60 # 60 × 10s = 10 dk
INTERVAL=10
echo "🔍 Polling deployment $DEPLOY_UUID"
for i in $(seq 1 $MAX); do
STATUS=$(curl -s --max-time 10 \
-H "Authorization: Bearer ${{ secrets.COOLIFY_API_TOKEN }}" \
"$DEPLOY_URL" 2>/dev/null | python3 -c "import json,sys; print(json.load(sys.stdin).get('status','?'))" 2>/dev/null || echo "unknown")
echo "[$i/$MAX] $STATUS"
case "$STATUS" in
finished|success)
echo "✅ Coolify deployment finished"
exit 0
;;
failed|error|cancelled)
echo "❌ Coolify deployment status: $STATUS"
echo "Panel: ${{ secrets.COOLIFY_BASE_URL }}"
exit 1
;;
esac
sleep $INTERVAL
done
echo "⚠️ Timeout — deployment hala '$STATUS' (10 dk geçti) — public URL health check'e geçiliyor"
- name: Public URL health check
run: |
MAX=15
INTERVAL=10
URL="https://trendyol.194.187.253.230.sslip.io"
for i in $(seq 1 $MAX); do
CODE=$(curl -sL -o /dev/null -w "%{http_code}" --max-time 10 "$URL" 2>/dev/null || echo "000")
echo "[$i/$MAX] $URL → HTTP $CODE"
if [ "$CODE" = "200" ] || [ "$CODE" = "302" ] || [ "$CODE" = "307" ]; then
echo "✅ Frontend canlı"
exit 0
fi
sleep $INTERVAL
done
echo "❌ Public URL erişilemez — Coolify panelini kontrol et"
exit 1
# ───────────────────────────────────────────────────────────────────────────
# Hata bildirimi — GitHub Issue otomatik aç
# ───────────────────────────────────────────────────────────────────────────
notify-failure:
name: 📢 Notify on Failure
needs: [validate-backend, validate-frontend, build-push-backend, build-push-frontend, deploy, verify]
runs-on: ubuntu-latest
if: failure()
permissions:
issues: write
steps:
- uses: actions/github-script@v7
with:
script: |
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
const shortSha = context.sha.substring(0, 7);
const title = `🚨 Deploy başarısız — Run #${context.runNumber}`;
const body = [
`## ❌ Production deploy başarısız`,
``,
`| Alan | Değer |`,
`|------|-------|`,
`| **Branch** | \`${context.ref.replace('refs/heads/', '')}\` |`,
`| **Commit** | \`${shortSha}\` |`,
`| **Run** | [#${context.runNumber}](${runUrl}) |`,
``,
`[Logları incele](${runUrl})`
].join('\n');
const { data: issues } = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
labels: 'deploy-failure',
state: 'open'
});
if (issues.length > 0) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issues[0].number,
body
});
} else {
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title,
body,
labels: ['deploy-failure']
});
}