Software Engineering

    Enterprise DevOps and CI/CD: GitHub Actions, GitLab, Monorepo and Deployment Pattern Guide

    Seven practical decisions for production-grade enterprise CI/CD: pipeline architecture (GitHub Actions vs GitLab CI vs Jenkins), monorepo vs polyrepo, deploy strategies (blue-green, canary, rolling), secret + artifact management, KVKK-compliant pipeline logs. Lessons from Turkish B2B projects. An eCloud Tech engineering note.

    Published: May 26, 202613 min read
    devopsci-cdgithub-actionsgitlab

    Enterprise software has transformed in deploy velocity over the past five years. Banks that used to ship 4 releases a year now ship 2 a week; e-commerce SaaS, 5-10 a day; modern startups, 50+. Behind this leap is CI/CD modernisation — from manual build/test/deploy to automated pipelines, from monolithic repos to monorepos, from ssh-deploy to GitOps + container orchestration. In Türkiye this shift is about 3 years behind; regulated sectors (banking, insurance, telco) sit in the Jenkins era, while e-commerce, B2B SaaS and AI startups are moving fast to GitHub Actions/GitLab CI. KVKK compliance, BDDK Information Systems Regulation, ISO 27001 audits — all expect provable discipline from a modern CI/CD pipeline.

    Within our DevOps + CI/CD engineering and cloud migration services we have delivered 16 enterprise CI/CD modernisation projects over the past 24 months — in finance, e-commerce, healthcare, logistics and SaaS. We operate our own AIGENCY platform on a GitHub Actions + Turborepo + GitOps architecture. In this article we walk through seven practical decisions for enterprise DevOps + CI/CD modernisation in order: pipeline platform choice, repo strategy (monorepo vs polyrepo), build optimisation, test automation, deployment patterns, secret + secret management, KVKK-compliant observability.

    1. Pipeline platform — GitHub Actions, GitLab CI, Jenkins decision matrix

    CI/CD platform choice is a skeletal decision — it shapes team workflow, cost structure and operational load for 5+ years.

    GitHub Actions:

    • Pro: zero-config integration with GitHub repo, marketplace of 15,000+ actions, simple YAML, included in GitHub's enterprise pricing. Native OIDC (trust with cloud-provider IAM).
    • Con: heterogeneous action ecosystem (each vendor sets its own quality, no security review), self-hosted runner setup (for KVKK) is extra effort.
    • Best fit: organisations living on GitHub, modern green-field projects, small-to-mid teams.

    GitLab CI/CD:

    • Pro: fully integrated with GitLab (issue, merge request, CI, registry, monitoring on one platform), self-hosted Community Edition is free, self-hosted runners by default.
    • Con: less widespread than GitHub, vendor lock-in (if you migrate to GitLab, git history + issues + PRs move).
    • Best fit: enterprise projects with self-hosted compliance needs, KVKK-critical sectors, those who want a single all-in-one platform.

    Jenkins:

    • Pro: 20 years of maturity, 1,800+ plugins, fully self-hosted, the "Swiss army knife" of build automation.
    • Con: Groovy DSL rather than YAML (extra learning), plugin-compatibility issues, Jenkins-master as a single point of failure, modern security practices (OIDC, dynamic secrets) require extra plugins.
    • Best fit: legacy Java/Maven projects, organisations with sunk Jenkins investment, on-prem requirements.

    CircleCI / Buildkite / Drone CI / Travis CI: niche; uncommon in Türkiye, rare in enterprise projects.

    Decision matrix:

    CriterionGitHub ActionsGitLab CI/CDJenkins
    Setup time<1 week1-2 weeks3-6 weeks
    Monthly cost (mid-size team)USD 200-1,500USD 0-1,000 (self-hosted free)Infrastructure only (~USD 200-1,000)
    Self-hosted runnerPossible, manualNativeNative
    OIDC + cloud IAMNativeNativePlugin
    Plugin / action ecosystemVery broadBroadBroadest but older
    KVKK self-hostedSelf-hosted runnerFull GitLab self-hostedFull self-hosted
    Modern UXExcellentGoodOld (Blue Ocean improves it)

    Practical recommendation: new project + on GitHub → Actions; on-prem/KVKK-critical → GitLab self-hosted; with existing Jenkins, plan a 6-12 month migration, don't migrate immediately.

    2. Repo strategy — monorepo vs polyrepo

    Repo strategy affects even organisational structure (Conway's law: software mirrors the organisation). The wrong choice produces a refactoring project in 1-2 years.

    Monorepo (single repo, multiple packages):

    • Tooling: Nx (TypeScript + Node heavy), Turborepo (Vercel, modern + fast), Bazel (Google, polyglot + huge scale), pnpm workspaces (simple + lightweight), Lerna (legacy).
    • Pro: atomic cross-package commits (UI + API + types in one PR), shared dep management (no version mismatch), refactor across the whole codebase, zero-friction code sharing (utils, types, UI library).
    • Con: CI complexity (build only affected packages — affected algorithm), repo size (need shallow clone), git operations slow down (large repo).
    • Sweet spot: TypeScript/JS heavy, shared UI/types, 1-3 teams, 5-15 packages.

    Polyrepo (every service/package in its own repo):

    • Pro: independent deploy cycles, team autonomy (each team owns its repo rules), small repo (fast clone), narrow blast radius (a bug in one service doesn't touch others).
    • Con: cross-repo change is hard (PR coordination), code duplication (utils copied to every repo), version mismatch (a shared SDK on 2 different versions in prod).
    • Sweet spot: independent microservices, polyglot (Go + Python + Node together), 10+ teams.

    Hybrid (middle ground):

    • Frontend + shared packages as one monorepo, backend microservices in separate repos.
    • The most common enterprise pattern; least compromise.

    Decision matrix:

    FactorMonorepoPolyrepo
    Team count1-55+
    Package count5-3030+ or 1-3
    Language diversity1-23+
    Cross-package change frequencyHighLow
    Deploy independenceLow (usually whole app together)High (each service independent)
    RefactoringVery easyHard

    Practical recommendation: PoC + early MVP = monorepo (speed + consistency); as organisation + service count grow drift selectively to polyrepo. Conservative: respect Conway's law — draw package boundaries to match organisational shape.

    3. Build optimisation — only affected packages

    A pipeline's single biggest performance lever is incremental build. Naive monorepo builds rebuild all 15 packages on every PR (12 min); smart incremental builds only the affected 2-3 (90 seconds).

    Build cache pattern:

    1. Local cache (developer machine): Turborepo, Nx, Bazel hash-based local cache. Second build in seconds.
    2. Remote cache (CI ↔ developer shared): Turborepo Remote Cache, Nx Cloud, Bazel Build Cache. Developer 1's build output is reused by CI and Developer 2. Hashed input → output mapping, S3/Redis backing.
    3. Docker layer cache: BuildKit --cache-to type=registry keeps the docker build cache in the image registry. Cache hits even when CI runners are ephemeral.

    Affected algorithm:

    • git diff origin/main...HEAD → changed files.
    • From the dependency graph, derive "affected packages" (transitive).
    • Only those are built + tested.
    • Nx nx affected --target=build, Turborepo turbo run build --filter=...[origin/main], Bazel native.

    Pipeline performance pattern:

    [git push]
        ↓
    [Lint + typecheck affected only] — 60-120s
        ↓
    [Unit test affected only] — 90-300s
        ↓ (parallel)
    [Build affected only] — 90-300s
    [Integration test critical paths] — 5-15min
        ↓
    [Deploy staging] — 60-120s
        ↓ (manual approval)
    [Deploy production] — 60-180s
    

    Unoptimised naive pipeline is 25-45 min; optimised is 5-10 min. A 3-5× improvement in developer productivity.

    Practical targets:

    • PR pipeline: <10 min (developer flow preserved)
    • Main-branch full build: <20 min
    • Production deploy: <5 min (CI end + actual deploy)

    Sustaining these targets requires CI-infrastructure investment + ongoing tuning. CI minute cost matters — a monthly USD 50K-200K GitHub Actions/GitLab CI bill is common in mid-to-large teams; with optimisation it drops 50-70%.

    4. Test automation — the trust spine of the pipeline

    Test pyramid (Mike Cohn): 70% unit + 20% integration + 10% e2e. The confidence CI provides depends on the existence + quality of each layer.

    Unit test:

    • Speed: <50ms/test, parallel execution.
    • Coverage target: 70-85% (sector-dependent). Higher targets have diminishing returns.
    • Tooling: Jest, Vitest (modern Node), pytest, Go test, JUnit.
    • In CI: on every PR, on the affected-package basis.

    Integration test:

    • Real HTTP/gRPC between services, real DB (test container), real queue.
    • Speed: 1-30s/test, sequential or constrained parallel.
    • Target: critical flows (auth, payment, core CRUD).
    • Tooling: Testcontainers (Docker-based throwaway env), Playwright (API + UI), Pact (contract testing).

    End-to-end (e2e) test:

    • Browser automation (Playwright, Cypress), full deployed app environment.
    • Speed: 10-60s/test, parallel + flaky risk.
    • Target: 10-50 critical user journeys (login → main task → logout).
    • Cadence: 5-10 critical tests in PR; full suite nightly.

    Flaky test management:

    • A flaky test in CI = lost trust + alert fatigue.
    • Detection: same test passes 2 out of 3 runs = flaky.
    • Quarantine: flaky tests are pulled from the main suite, run in a separate job, fixed in a weekend sprint.
    • Zero tolerance: leaving flaky tests in place corrodes pipeline quality.

    Security testing in CI:

    • SAST: Semgrep, Snyk Code, GitHub CodeQL (every PR).
    • SCA (dependency vulnerability): Dependabot, Renovate + Snyk/Trivy (every PR).
    • DAST: OWASP ZAP, Burp Suite (after staging deploy).
    • Container scan: Trivy, Grype (after Docker build).
    • IaC scan: Checkov, tfsec (on Terraform PRs).

    Pipeline test coverage matrix:

    StageTests
    PR openLint + typecheck + unit + SAST + dependency scan
    PR merge to main+ integration + container scan + e2e smoke
    Staging deploy+ full e2e + DAST + performance test
    Production deploy+ post-deploy smoke + monitoring sync

    5. Deployment patterns — rolling, blue-green, canary

    The deploy pattern is chosen by risk tolerance + sector + budget.

    Rolling deployment:

    • Restart N instances in 2-N steps (e.g. 10 instances → roll 2 at a time, 5 steps).
    • Kubernetes default (RollingUpdate strategy).
    • Pro: zero extra infra, simple, auto in most PaaS.
    • Con: rollback is slow (reverse rollout), old + new live simultaneously → DB schema breaking changes are problematic.
    • Sweet spot: stateless services, small-to-mid teams, SMBs.

    Blue-green deployment:

    • Two full parallel environments: blue (current prod) + green (new). Switch via DNS/LB.
    • Zero-downtime, instant rollback (flip DNS back).
    • Pro: production-identical testing (test green prod-fashion), second-level rollback on incident.
    • Con: 2× infra cost, single DB (can't parallelise — schema migration must be backwards-compatible).
    • Sweet spot: B2B SaaS, regulated sectors, financial transactions.

    Canary deployment:

    • New version traffic split: 1% → 5% → 25% → 50% → 100%. At every step a metric (error rate, latency, business KPI) is monitored.
    • Automatic rollback: if error rate exceeds threshold, fall back to old.
    • Pro: validation on real production traffic, safest, "free" if you already have A/B testing.
    • Con: feature-flag system required (LaunchDarkly, Unleash, custom), observability must be mature, complex.
    • Sweet spot: high-volume consumer (e-commerce, social), millions of users.

    Modern hybrid: Argo Rollouts, Flagger, Spinnaker — Kubernetes-native canary + blue-green orchestration. Combine with a service mesh (Istio, Linkerd) for traffic splitting + observability integration.

    GitOps (Argo CD, Flux):

    • Deploy state is declarative in a Git repo (Helm charts, Kustomize manifests).
    • Production = projection of Git. No manual kubectl apply.
    • Automatic drift detection + reconciliation (if cluster differs from Git, cluster is corrected).
    • Audit trail: who deployed what when → Git commit history.
    • Ideal from a KVKK + compliance perspective: change evidence is immutable.

    Practical decision matrix:

    Sector / ScenarioRecommended
    SMB web/app, <50K usersRolling
    Mid-size B2B SaaS, 50K-500KBlue-green
    E-commerce, finance, >500KCanary + GitOps
    Banking coreBlue-green + canary hybrid + extensive manual approval
    Microservice mesh, >20 servicesGitOps + Argo Rollouts

    6. Secret + artifact management — the pipeline's security gate

    A CI/CD pipeline is the central point for credentials (DB password, cloud IAM key, API token, SSL cert). Wrong management = breach source.

    Secret management pattern stack:

    [Developer]
        ↓ (commit code, NO secrets in repo)
    [Git repo] — .gitignore .env, pre-commit secret scan (git-secrets, truffleHog)
        ↓
    [CI runner]
        ↓ (fetch at runtime)
    [Secret store: Vault / Secrets Manager / Key Vault]
        ↓ (short-lived token via OIDC)
    [Application]
    

    Layer 1 — Repo discipline:

    • .env in .gitignore, git secrets --register-aws global hook.
    • Pre-commit: husky + lint-staged + secret pattern scan.
    • Repo history scan (BFG, git-filter-repo) — if secrets leaked in the past, rotate.

    Layer 2 — CI native secret store:

    • GitHub Actions: Settings → Secrets and variables → Actions. Masked output, environment-scoped, branch-protected.
    • GitLab: Settings → CI/CD → Variables. Protected, masked, expand variables.
    • Jenkins: Credentials Plugin + folder-level scoping.
    • Every access is logged.

    Layer 3 — External secret manager:

    • HashiCorp Vault: self-hosted, most widely adopted in enterprises, dynamic secret generation (DB credential is created when pipeline calls + 1-hour TTL).
    • AWS Secrets Manager / Azure Key Vault / GCP Secret Manager: cloud-native, vendor lock-in.
    • Doppler, 1Password Secrets Automation: modern SaaS alternative.
    • Vault is mandatory for KVKK-critical organisations (data residency + audit log + access control matrix).

    Layer 4 — OIDC trust (short-lived credentials):

    • GitHub Actions ↔ AWS IAM Role: GitHub identity token → AWS STS AssumeRole → 15-min temporary credentials.
    • Static IAM access keys become unnecessary — the chance of a credential leak goes to zero.
    • Setup: GitHub Actions workflow + AWS IAM OIDC provider + Role trust policy.

    Layer 5 — Audit + rotation:

    • Every secret access is logged (CloudTrail, Vault audit log, GitLab audit events).
    • 90-day automated rotation policy.
    • Unused secrets are revoked after 30 days.
    • Quarterly access review (who still needs which secret).

    Artifact management:

    • Docker image: GitHub Container Registry (ghcr.io), Docker Hub, AWS ECR, Harbor (self-hosted).
    • Build artifact (jar, npm pkg): GitHub Packages, JFrog Artifactory, Nexus (self-hosted).
    • Retention policy: prod tags forever, PR builds 30 days, scheduled prune.
    • Signing: Sigstore Cosign, Notary v2 — supply-chain integrity (did this image really come from our CI?).

    Our SOC operations article details how CI/CD pipeline logs integrate into the SOC SIEM.

    7. KVKK-compliant observability + audit

    CI/CD pipelines do not seem to process personal data, but indirectly they do: developer identity (commit author), deploy decision (who approved), test data in pipeline logs (mock customer email), production access (debug session). KVKK + ISO 27001 audits require written discipline.

    Seven disciplines:

    1. Immutable pipeline run logs: GitHub Actions / GitLab CI run history (default 90 days, 400 days on enterprise). 12 months + retention policy in writing for KVKK audit.

    2. Developer identity (commit) policy: verified commits (GPG/SSH signed) mandatory, no anonymous commits. Evidence: who wrote what, who merged.

    3. Approval gates auditable: 2 reviewers required for production deploy (GitHub branch protection rule); each approval logs who + when + commit SHA.

    4. Test data sanitisation: no real customer email/national ID/IBAN in test fixtures. Faker library + synthetic data. No PII should appear in CI logs.

    5. Production debug log access: pipeline-to-prod debug session limited (break-glass procedure), each access logged + post-hoc justification.

    6. Secret access audit: which pipeline run called which secret → Vault audit log + correlation by pipeline run ID.

    7. Compliance reporting: monthly report — number of deploys, rollbacks, hotfixes, incidents. Goes into KVKK risk assessment.

    Observability stack:

    • Pipeline metrics: DORA metrics (deploy frequency, lead time, change failure rate, MTTR) — state-of-the-art DevOps KPIs. Trackers: LinearB, Sleuth, DX Engineering Effectiveness.
    • Build performance: cache hit rate, average pipeline duration, queue time, runner utilisation.
    • Cost tracking: GitHub Actions usage report, GitLab CI minute analytics, cloud-runner spot pricing.
    • Failure analytics: flaky test detection, distinguishing infrastructure failure from code failure.

    DORA metrics targets (DORA Elite tier):

    • Deploy frequency: 1+ per day
    • Lead time for changes: <1 hour (commit → prod)
    • Change failure rate: <15%
    • MTTR (failed change recovery): <1 hour

    Reaching these targets takes years; the enterprise average (Medium tier): 1-7 deploys per week, <1-day lead time, 15-30% failure rate, <1-day MTTR.

    Practical summary — starting checklist

    The correct order for your first production CI/CD modernisation project:

    1. Platform: GitHub repo → Actions; on-prem/KVKK → GitLab self-hosted; legacy → plan a Jenkins migration.
    2. Repo strategy: 1-3 teams + JS/TS = monorepo (Turborepo/Nx); 5+ teams + polyglot = polyrepo; hybrid is the most common.
    3. Build optimisation: affected algorithm + remote cache + Docker layer cache. PR pipeline target <10 min.
    4. Test pyramid: 70% unit + 20% integration + 10% e2e; zero tolerance for flaky; SAST + SCA + DAST + IaC scan in CI.
    5. Deployment pattern: SMB rolling; mid-size B2B blue-green; high-volume canary; GitOps (Argo CD) ideal for compliance.
    6. Secret management: Vault or cloud manager + OIDC short-lived credentials + audit + 90-day rotation.
    7. Artifact management: image registry + signing (Cosign) + retention policy.
    8. KVKK observability: pipeline log 12-month retention, verified commits, audited approval gates, test data sanitisation.
    9. DORA metrics: deploy frequency / lead time / failure rate / MTTR — monthly dashboard.
    10. Continuous improvement: quarterly platform retro, CI cost optimisation, security training, runbook updates.

    This list is the minimum discipline. On top come sector-specific additions (deploy controls for PSD2 payment services, FDA validation pipeline for medical devices, change-management evidence for ISO 27001). The value of CI/CD is not in being live but in weekly measurable improvement of DORA metrics — the numerical trend curve for deploy velocity + confidence + recoverability.

    Our team in Şanlıurfa Karaköprü has delivered CI/CD modernisation projects in finance, e-commerce, healthcare and logistics through DevOps + CI/CD engineering and cloud migration, and operates our own AIGENCY platform on GitHub Actions + Turborepo + GitOps. For an enterprise CI/CD modernisation pilot, a DORA-metric audit of your existing pipeline, or monorepo/polyrepo decision advisory, you can reach us through the contact form — the first assessment call is free of charge.


    eCloud Tech — A team based in Şanlıurfa, Türkiye, working on enterprise software, AI, blockchain and cybersecurity. Building Tomorrow.

    Frequently Asked Questions

    The decision rests on three variables. (1) Repo hosting: CI naturally lives where your code lives — on GitHub → GitHub Actions (annual plan from USD 21/user, 50K Actions minutes included), on GitLab → GitLab CI/CD (integrated, self-hosted runner is free). This alignment is the right answer in ~80% of cases. (2) Self-hosted compliance need: if a KVKK-critical organisation requires the runner on Türkiye soil, self-hosted GitLab or Jenkins dominate. Even on cloud CI, self-hosted runners are possible. (3) Legacy + Java/Maven-heavy: the mature Jenkins ecosystem (1,800+ plugins) still dominates. Picking Jenkins on a modern green-field project produces technical debt in 6-12 months. CircleCI is popular in mid-to-large SaaS companies but uncommon in Türkiye. Practical advice: if you're on GitHub, use Actions; if you need on-prem/self-hosted, GitLab self-hosted; in a modernisation project the Jenkins → Actions/GitLab migration pattern is standard.

    Related articles