CI/CD Pipeline
5 minute read
CI/CD Pipeline
Denomas, tüm projelerinde GitLab CI/CD kullanır. Pipeline, kodun commit edilmesinden üretim ortamına deploy edilmesine kadar tüm aşamaları otomatize eder. CI/CD altyapısı code.denomas.com ve code.ilimteknoloji.com adreslerindeki self-hosted GitLab instance'ları üzerinde çalışır.
Pipeline Aşamaları
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐ ┌──────────────┐
│ lint │ → │ test │ → │ build │ → │ scan │ → │ deploy-staging │ → │ deploy-prod │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └────────────────┘ └──────────────┘
1. lint
- Pre-commit hook doğrulaması (
pre-commit run --all-files) - Python: ruff lint + ruff-format kontrolü + mypy tip kontrolü
- JavaScript: ESLint (airbnb-base preset)
- YAML/JSON format kontrolü (yamllint)
- Ansible: ansible-lint
- Docker: hadolint
- Shell: shellcheck
- Docstring kontrolü (public fonksiyonlarda zorunlu)
- Conventional Commit format kontrolü
2. test
- Birim testleri —
pytest --cov=src --cov-fail-under=80 - Entegrasyon testleri — API endpoint testleri, veritabanı migration testleri
- Odoo testleri — Odoo test framework ile modül testleri (
odoo-bin --test-enable) - Ansible testleri —
molecule testile rol doğrulaması - Kapsam raporu oluşturma (Cobertura formatı, GitLab MR'da görselleştirme)
3. build
- Docker image oluşturma (multi-stage build)
- Semantic versiyon etiketi (
$CI_COMMIT_TAGveya$CI_COMMIT_SHORT_SHA) - Docker image'ı GitLab Container Registry'ye push
- Ansible artifact'ları paketleme (roller + playbook'lar)
- Hugo site build (handbook ve website projeleri için)
4. scan
- SAST: Bandit (Python), Semgrep (
p/owasp-top-tenruleset), GitLab SAST template - Dependency Scan: Trivy (container + dependency CVE taraması)
- Lisans Kontrolü: Uyumsuz lisans tespiti (GPL kontrol)
- Container Image Scan: Trivy ile Docker image güvenlik taraması
- Secret Detection: GitLab Secret Detection template
5. deploy-staging
- Ansible playbook ile staging ortamına deploy (
ansible-playbook deploy-staging.yml) - Otomatik smoke testleri (
ansible-playbook smoke-test.yml) - Performans testi (k6 ile yük testi)
- Staging URL'i MR'a yorum olarak eklenir
6. deploy-prod
- Dual-track deployment stratejisine göre
- Track 1 (SaaS):
mainmerge sonrasıwhen: manualonay → canary deploy → kademeli rollout - Track 2 (Self-Managed): Release tag'i sonrası paketleme ve dağıtım
- Production deploy sonrası otomatik health check
Tam .gitlab-ci.yml Örneği
# .gitlab-ci.yml — Denomas standart pipeline
image: python:3.10-slim
variables:
# Genel
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
PRE_COMMIT_HOME: "$CI_PROJECT_DIR/.cache/pre-commit"
# Docker
DOCKER_IMAGE: "$CI_REGISTRY_IMAGE"
DOCKER_TAG: "$CI_COMMIT_SHORT_SHA"
# Deployment
ANSIBLE_INVENTORY: "inventory/$CI_ENVIRONMENT_NAME"
ANSIBLE_FORCE_COLOR: "true"
# SAST
SAST_EXCLUDED_PATHS: "tests/,migrations/,docs/"
SECURE_LOG_LEVEL: "warn"
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .cache/pip
- .cache/pre-commit
- .venv/
stages:
- lint
- test
- build
- scan
- deploy-staging
- deploy-prod
# ─── LINT ─────────────────────────────────────────────
lint:pre-commit:
stage: lint
script:
- pip install pre-commit
- pre-commit run --all-files
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == "develop"'
lint:mypy:
stage: lint
script:
- pip install -r requirements-dev.txt
- mypy src/ --ignore-missing-imports
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
allow_failure: false
# ─── TEST ─────────────────────────────────────────────
test:unit:
stage: test
services:
- postgres:15-alpine
- redis:7-alpine
variables:
POSTGRES_DB: test_db
POSTGRES_USER: test_user
POSTGRES_PASSWORD: $CI_DB_PASSWORD
DATABASE_URL: "postgresql://test_user:$CI_DB_PASSWORD@postgres:5432/test_db"
REDIS_URL: "redis://redis:6379/0"
script:
- pip install -r requirements-dev.txt
- pytest --cov=src --cov-report=xml --cov-report=term --cov-fail-under=80
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: coverage.xml
expire_in: 30 days
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == "develop"'
test:integration:
stage: test
services:
- postgres:15-alpine
- redis:7-alpine
script:
- pip install -r requirements-dev.txt
- pytest tests/integration/ -v --tb=short
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
# ─── BUILD ────────────────────────────────────────────
build:docker:
stage: build
image: docker:24.0
services:
- docker:24.0-dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $DOCKER_IMAGE:$DOCKER_TAG -t $DOCKER_IMAGE:latest .
- docker push $DOCKER_IMAGE:$DOCKER_TAG
- docker push $DOCKER_IMAGE:latest
rules:
- if: '$CI_COMMIT_BRANCH == "develop"'
- if: '$CI_COMMIT_BRANCH == "main"'
- if: '$CI_COMMIT_TAG'
# ─── SCAN ─────────────────────────────────────────────
scan:bandit:
stage: scan
script:
- pip install bandit[toml]
- bandit -c pyproject.toml -r src/ -f json -o bandit-report.json
artifacts:
paths:
- bandit-report.json
expire_in: 30 days
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
scan:semgrep:
stage: scan
image: returntocorp/semgrep
script:
- semgrep --config=p/owasp-top-ten --config=p/python --json -o semgrep-report.json src/
artifacts:
paths:
- semgrep-report.json
expire_in: 30 days
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
scan:trivy:
stage: scan
image:
name: aquasec/trivy:latest
entrypoint: [""]
script:
- trivy image --exit-code 1 --severity HIGH,CRITICAL $DOCKER_IMAGE:$DOCKER_TAG
rules:
- if: '$CI_COMMIT_BRANCH == "develop"'
- if: '$CI_COMMIT_BRANCH == "main"'
include:
- template: Security/SAST.gitlab-ci.yml
- template: Security/Secret-Detection.gitlab-ci.yml
# ─── DEPLOY STAGING ───────────────────────────────────
deploy_staging:
stage: deploy-staging
image: ansible/ansible-runner:latest
script:
- ansible-playbook deploy-staging.yml -e "docker_tag=$DOCKER_TAG"
- ansible-playbook smoke-test.yml -e "environment=staging"
environment:
name: staging
url: https://staging.denomas.com
rules:
- if: '$CI_COMMIT_BRANCH == "staging"'
# ─── DEPLOY PRODUCTION ───────────────────────────────
deploy_canary:
stage: deploy-prod
image: ansible/ansible-runner:latest
script:
- ansible-playbook deploy-canary.yml -e "docker_tag=$DOCKER_TAG canary_weight=5"
environment:
name: canary
url: https://canary.denomas.com
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual
deploy_production:
stage: deploy-prod
image: ansible/ansible-runner:latest
script:
- ansible-playbook deploy-production.yml -e "docker_tag=$DOCKER_TAG"
- ansible-playbook smoke-test.yml -e "environment=production"
environment:
name: production
url: https://denomas.com
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual
needs: ["deploy_canary"]
Ortam Değişkenleri (CI/CD Variables)
| Değişken | Tür | Kapsam | Açıklama |
|---|---|---|---|
CI_REGISTRY_USER | Protected | Tüm projeler | GitLab Container Registry kullanıcı |
CI_REGISTRY_PASSWORD | Protected, Masked | Tüm projeler | GitLab Container Registry parola |
CI_DB_PASSWORD | Protected, Masked | Tüm projeler | Test veritabanı parolası |
ANSIBLE_SSH_KEY | Protected, File | Deploy projeleri | Deployment SSH anahtarı |
SENTRY_DSN | Protected | Production | Hata izleme DSN |
GRAFANA_API_KEY | Protected, Masked | Monitoring | Grafana dashboard API |
VAULT_TOKEN | Protected, Masked | Production | HashiCorp Vault erişim token |
Hassas değerler asla .gitlab-ci.yml içinde açık metin olarak yazılmaz. Tüm sırlar GitLab CI/CD Variables'da Protected ve Masked olarak tanımlanır. Detaylar için Mimari Prensipler — Zero Trust
bölümüne bakınız.
Ortamlar
| Ortam | URL | Amaç | Deploy Tetikleme |
|---|---|---|---|
| Development | dev.denomas.com | Geliştirici testleri, feature branch doğrulaması | Her MR push (otomatik) |
| Staging | staging.denomas.com | Canlıya çıkmadan önceki son test | staging dalına merge (otomatik) |
| Canary | canary.denomas.com | Ön-üretim doğrulama, %5 trafik | main merge sonrası (manuel onay) |
| Production | denomas.com | Canlı ortam | Canary başarılı sonrası (manuel onay) |
Artifact Yönetimi
| Artifact Tipi | Depolama | Saklama Süresi |
|---|---|---|
| Test kapsam raporları (Cobertura XML) | GitLab Job Artifacts | 30 gün |
| SAST raporları (JSON) | GitLab Job Artifacts | 30 gün |
| Docker image'lar | GitLab Container Registry | Son 10 tag + latest |
| Ansible playbook arşivleri | GitLab Package Registry | Süresiz (release tag'leri) |
| k6 performans raporları | GitLab Job Artifacts | 90 gün |
Pipeline Performans Hedefleri
| Aşama | Hedef Süre | Mevcut Ortalama |
|---|---|---|
lint | < 2 dakika | Pipeline metriklerinden izlenir |
test | < 10 dakika | Pipeline metriklerinden izlenir |
build | < 5 dakika | Pipeline metriklerinden izlenir |
scan | < 8 dakika | Pipeline metriklerinden izlenir |
| Toplam Pipeline | < 25 dakika | Haftalık raporlanır |
Deployment adımları Denomas Yönetim Otomasyon Ansible playbook'ları ile yürütülür. Bu, tutarlı ve tekrarlanabilir deployment sağlar. Tüm deployment playbook'ları idempotent olmalıdır.
Yapay Zeka Asistanları CI/CD pipeline sonuçlarını okuyabilir ve başarısız aşamalar için düzeltme önerisi sunabilir. Pipeline tetikleme yetkisi Denomas Yetkinlik Çerçevesi seviye 4+ gerektirir. Production deploy onay yetkisi sadece insanlara aittir (when: manual).
İlgili Sayfalar
- Mühendislik Genel Bakış
- Kod Kalitesi
- Sürüm Süreci
- Kod İnceleme
- Denomas Yönetim Otomasyon
- Mimari Prensipler
Geribildirim
Bu sayfa yararlı oldu mu?
Bu sayfa faydali oldu
Bu sayfa gelistirilmeli
