didi-lot2-backend/backend/.gitlab-ci.yml
EVOTECH IT SRL 7e4f23d4c4 Optimizare scripturi build/CI si functionalitati noi Lot 2
- CI/CD GitLab (.gitlab-ci.yml): verify -> test -> build -> publish ->
  deploy cu health-gate (/api/v3/health/all) + rollback manual
- Publicare pe retele sociale (LinkedIn/Facebook) din Analysis History
  (social.ts, linkedin.ts, facebook.ts, SocialPostModal)
- Specificatii OpenAPI: agent-v3 (87 op.) si didi-framework (287 op.)
- Matrice testare acceptanta beneficiar + script dovezi API
- Fix nginx SSL: redirect port 3001 (error_page 497, absolute_redirect off)
- Adrese interne inlocuite cu hostname-uri generice (.local)
2026-07-12 13:36:08 -07:00

178 lines
7.2 KiB
YAML

# =============================================================================
# DiDi Lot 2 (Backend) — Pipeline CI/CD GitLab
# =============================================================================
# Etape: verify (typecheck) → test (unitare) → build (imagini Docker, versionate)
# → publish (registry) → deploy (cu HEALTH-GATE) → rollback (manual)
#
# Variabile așteptate în GitLab (Settings → CI/CD → Variables):
# CI_REGISTRY / CI_REGISTRY_USER / CI_REGISTRY_PASSWORD — registry-ul de imagini
# DEPLOY_HOST — host-ul de deployment (SSH)
# DEPLOY_USER — utilizatorul de deployment
# Versionare imagini: $CI_COMMIT_SHORT_SHA (+ tag "latest" doar pe branch-ul implicit).
# Rollback: job manual care re-etichetează imaginea anterioară (previous) ca latest
# și redeployează — mecanismul de revenire cerut de documentație.
# =============================================================================
stages:
- verify
- test
- build
- publish
- deploy
- rollback
default:
interruptible: true
variables:
DOCKER_TLS_CERTDIR: "/certs"
AGENT_DIR: services/orchestration-layer/agent-v3
FRAMEWORK_DIR: services/orchestration-layer/didiFramework
DASHBOARD_DIR: admin-dashboard
# ---------- șabloane reutilizabile ----------
.node:
image: node:20-alpine
before_script:
- node --version && npm --version
.docker:
image: docker:27
services: [docker:27-dind]
before_script:
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
# =============================================================================
# VERIFY — compilare TypeScript (fără emitere) pe toate serviciile
# =============================================================================
verify:agent-v3:
stage: verify
extends: .node
script:
- cd $AGENT_DIR && npm ci --prefer-offline
- npx tsc --noEmit
rules: [{ changes: ["services/orchestration-layer/agent-v3/**/*"] }, { when: always }]
verify:framework:
stage: verify
extends: .node
script:
- cd $FRAMEWORK_DIR && npm ci --prefer-offline
- npx tsc --noEmit
verify:dashboard:
stage: verify
extends: .node
script:
- cd $DASHBOARD_DIR && npm ci --prefer-offline
- npm run type-check
# =============================================================================
# TEST — teste unitare (vitest pe agent-v3; raport JUnit pentru GitLab)
# =============================================================================
test:agent-v3:
stage: test
extends: .node
script:
- cd $AGENT_DIR && npm ci --prefer-offline
- npx vitest run --reporter=default --reporter=junit --outputFile=vitest-junit.xml
artifacts:
when: always
reports:
junit: $AGENT_DIR/vitest-junit.xml
expire_in: 30 days
# validarea specificațiilor OpenAPI livrate (criteriul 6 — OpenAPI/Swagger)
test:openapi:
stage: test
image: python:3.12-alpine
script:
- pip install --quiet openapi-spec-validator pyyaml
- python -c "from openapi_spec_validator import validate; import yaml; validate(yaml.safe_load(open('$AGENT_DIR/openapi.yaml')))"
- python -c "from openapi_spec_validator import validate; import yaml; validate(yaml.safe_load(open('$FRAMEWORK_DIR/openapi.yaml')))"
# =============================================================================
# BUILD — imagini Docker versionate cu SHA-ul commit-ului
# =============================================================================
build:agent-v3:
stage: build
extends: .docker
script:
- docker build -t "$CI_REGISTRY_IMAGE/agent-v3:$CI_COMMIT_SHORT_SHA" $AGENT_DIR
- docker push "$CI_REGISTRY_IMAGE/agent-v3:$CI_COMMIT_SHORT_SHA"
build:framework:
stage: build
extends: .docker
script:
- docker build -t "$CI_REGISTRY_IMAGE/didi-framework:$CI_COMMIT_SHORT_SHA" $FRAMEWORK_DIR
- docker push "$CI_REGISTRY_IMAGE/didi-framework:$CI_COMMIT_SHORT_SHA"
build:dashboard:
stage: build
extends: .docker
script:
- docker build -t "$CI_REGISTRY_IMAGE/didi-admin:$CI_COMMIT_SHORT_SHA" $DASHBOARD_DIR
- docker push "$CI_REGISTRY_IMAGE/didi-admin:$CI_COMMIT_SHORT_SHA"
# =============================================================================
# PUBLISH — pe branch-ul implicit, promovăm SHA-ul la :latest și păstrăm
# :previous (ținta de rollback)
# =============================================================================
publish:latest:
stage: publish
extends: .docker
rules: [{ if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' }]
script:
- |
for svc in agent-v3 didi-framework didi-admin; do
# păstrează versiunea curentă ca :previous (rollback target)
docker pull "$CI_REGISTRY_IMAGE/$svc:latest" || true
docker tag "$CI_REGISTRY_IMAGE/$svc:latest" "$CI_REGISTRY_IMAGE/$svc:previous" || true
docker push "$CI_REGISTRY_IMAGE/$svc:previous" || true
# promovează build-ul curent
docker pull "$CI_REGISTRY_IMAGE/$svc:$CI_COMMIT_SHORT_SHA"
docker tag "$CI_REGISTRY_IMAGE/$svc:$CI_COMMIT_SHORT_SHA" "$CI_REGISTRY_IMAGE/$svc:latest"
docker push "$CI_REGISTRY_IMAGE/$svc:latest"
done
# =============================================================================
# DEPLOY — cu HEALTH-GATE: deploy-ul e considerat reușit DOAR dacă
# /api/v3/health/all răspunde healthy/degraded după repornire
# =============================================================================
deploy:production:
stage: deploy
image: alpine:3.20
rules: [{ if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH', when: manual }]
environment: { name: production }
before_script: [ "apk add --no-cache openssh-client curl" ]
script:
- ssh -o StrictHostKeyChecking=accept-new "$DEPLOY_USER@$DEPLOY_HOST" "
cd ~/didi/backend/services/orchestration-layer/agent-v3 && docker compose pull && docker compose up -d &&
cd ../didiFramework && docker compose pull && docker compose up -d"
# HEALTH-GATE: max 120s până când platforma raportează sănătate
- |
for i in $(seq 1 24); do
code=$(ssh "$DEPLOY_USER@$DEPLOY_HOST" "curl -sk -o /dev/null -w '%{http_code}' http://localhost:24803/api/v3/health/all" || echo 000)
echo "health-gate încercarea $i: HTTP $code"
[ "$code" = "200" ] && exit 0
sleep 5
done
echo "HEALTH-GATE EȘUAT — deploy-ul NU este sănătos"; exit 1
# =============================================================================
# ROLLBACK — manual: repune imaginile :previous și redeployează
# =============================================================================
rollback:production:
stage: rollback
extends: .docker
rules: [{ if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH', when: manual }]
environment: { name: production }
script:
- |
for svc in agent-v3 didi-framework didi-admin; do
docker pull "$CI_REGISTRY_IMAGE/$svc:previous"
docker tag "$CI_REGISTRY_IMAGE/$svc:previous" "$CI_REGISTRY_IMAGE/$svc:latest"
docker push "$CI_REGISTRY_IMAGE/$svc:latest"
done
- echo "Imaginile anterioare repromovate la :latest — rulați deploy:production pentru a le aplica."