GitLab CI/CD is built-in continuous integration and deployment platform integrated directly into GitLab (no separate CI tool needed). In GitLab 17.x, pipelines are defined in .gitlab-ci.yml (YAML) in repository root or using reusable CI/CD components from the CI/CD Catalog (GA in GitLab 17.0). Core workflow: commit → GitLab detects .gitlab-ci.yml → creates pipeline → runners execute jobs → artifacts/deployments. Components: jobs (executable tasks), stages (sequential groups), runners (execution agents with Docker/Kubernetes/Shell executors). GitLab 17 features: component-based configs (include: - component: gitlab.com/org/[email protected]), Auto DevOps with deployment strategies (continuous/canary/blue-green), built-in security scanning (SAST/DAST), Kubernetes integration. Free tier includes shared runners. Default stages: .pre, build, test, deploy, .post. GitLab 17.11+ improved runner management with job history tracking.
Gitlab Ci FAQ & Answers
31 expert Gitlab Ci answers researched from official documentation. Every answer cites authoritative sources you can verify.
unknown
31 questionsYAML file defines pipeline configuration in GitLab 17.x. Global keywords: stages (define workflow order), variables (CI/CD variables), include (import configs/components), workflow (pipeline-level rules). Modern GitLab 17 includes support components via include: - component: gitlab.com/org/[email protected] with parameterized inputs. Job structure: job_name: { stage: build, script: [commands], rules: [conditions], artifacts: {paths: [build/]}, cache: {paths: [node_modules/]} }. Example: build_job: stage: build, script: - npm install, - npm run build, artifacts: paths: [dist/], expire_in: 1 week. Jobs in same stage run parallel (up to runner concurrency), stages run sequentially. Default stages: .pre, build, test, deploy, .post. Validate with CI Lint tool (CI/CD > Editor > Validate) or API before commit. GitLab 17 supports multi-cache configurations (max 4 caches per job).
Job: unit of work in pipeline executed by GitLab Runner (build, test, deploy). Define: job_name: { script: [commands], stage: build, tags: [docker] }. In GitLab 17.x, jobs can bypass stage order using needs keyword to create DAG (Directed Acyclic Graph) pipelines. Stage: groups jobs, controls execution order. Default stages: .pre, build, test, deploy, .post. Jobs within same stage execute in parallel (limited by runner concurrency), subsequent stages wait for previous stage completion. Custom stages: stages: [compile, test, package, deploy]. Job assignment: stage: test. Hidden jobs (start with dot): reusable templates via extends. GitLab 17 optimization: use needs: [job1, job2] to start jobs immediately after dependencies complete (max 50 needs per job), reducing pipeline duration by 40-80% for complex workflows. Example: test: needs: [build], script: [npm test] runs as soon as build completes.
Artifacts: files stored on GitLab server after job execution for passing data between jobs. Define: artifacts: { paths: [build/, dist/], expire_in: 1 week, when: on_success }. In GitLab 17.x, artifacts upload after successful job completion by default. Subsequent jobs automatically download artifacts from previous stages, or specific jobs via dependencies: [job1] or needs: [job2] (needs automatically downloads artifacts). Features: automatic expiration (cleanup storage), reports (junit/cobertura/SAST), exclude patterns. When values: on_success (default), on_failure (debug logs), always (both). Access: job page UI, REST API, or dependencies keyword. Artifacts restore after caches during job setup. GitLab 17 best practice: set expire_in to minimize storage costs (default: 30 days configurable per instance). Example: test: dependencies: [build], script: [./run-tests] downloads only build job artifacts, not entire previous stage.
Cache: optimization for storing dependencies (node_modules, .m2, gems) shared between pipelines/jobs, restored before artifacts during job setup. GitLab 17 supports max 4 caches per job via cache: [{ key: gems, paths: [vendor/] }, { key: npm, paths: [node_modules/] }]. Cache policies: pull (download only), push (upload only), pull-push (default). Artifacts: job outputs (build/, dist/) stored on GitLab server, downloaded by subsequent jobs. Key differences: (1) Purpose: cache = speed optimization, artifacts = job output passing. (2) Scope: cache shared across pipelines, artifacts job-specific. (3) Restoration: caches restore first, then artifacts. (4) Storage: cache in runner/S3, artifacts on GitLab server. GitLab 17 best practice: use pull policy for read-only cache jobs (tests), pull-and-push-if-changed pattern for cache updates to reduce upload time. Example: test: cache: { key: deps, paths: [node_modules/], policy: pull }.
Rules: conditionally execute jobs using if (expressions), changes (file patterns), exists (file presence), variables (override job vars). In GitLab 17.x, rules replace deprecated only/except syntax with more powerful logic. Syntax: rules: - if: $CI_COMMIT_BRANCH == 'main', when: always. Multiple conditions support AND/OR logic: rules: - if: '$CI_COMMIT_BRANCH == "main" && $CI_PIPELINE_SOURCE == "merge_request_event"'. Common patterns: (1) MR-only: rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event'. (2) File changes: rules: - changes: [src/**/*.js], when: on_success. (3) Protected branches: rules: - if: $CI_COMMIT_REF_PROTECTED == 'true'. GitLab 17 enhancement: rules: exists for checking file presence before job execution. Example: deploy: rules: - if: '$CI_COMMIT_BRANCH == "main"', - if: '$CI_COMMIT_TAG =~ /^v[0-9]+/', when: manual. Best practice: combine workflow:rules (pipeline-level) with job rules for precise control.
When: controls job execution timing in GitLab 17.x pipelines. Values: on_success (default, runs after previous stage success), on_failure (runs after previous stage failure), manual (requires human click, shows orange play button), delayed (runs after start_in delay), always (runs regardless of previous status), never (skips job, workflow:rules only). Example: deploy: { stage: deploy, when: manual, allow_failure: false, script: [./deploy.sh] } creates blocking manual gate. Delayed example: notify: { when: delayed, start_in: 3 hours, script: [./notify.sh] } waits 3 hours. GitLab 17 use cases: (1) Production deploys: when: manual with protected environments. (2) Cleanup: when: always in after_script. (3) Failure alerts: when: on_failure. (4) Deployment gates: when: manual + allow_failure: false pauses pipeline. Manual jobs default to allow_failure: true (non-blocking); set allow_failure: false for approval workflows.
Variables: configuration values available in GitLab 17.x pipelines. Types: (1) Predefined (CI_COMMIT_SHA, CI_PROJECT_NAME, CI_PIPELINE_SOURCE). (2) Custom (Settings > CI/CD > Variables). (3) Group/instance variables (inherited). Define in YAML: variables: { DB_NAME: mydb, NODE_ENV: production }. Access: $VARIABLE or ${VARIABLE} in scripts. Variable attributes: Protected (only protected branches/tags), Masked (hide in logs with ***), File (write value to temp file path). GitLab 17.0+ supports ID tokens for OIDC authentication (id_tokens: VAULT_TOKEN: { aud: vault.example.com }). Precedence: job > global YAML > project > group > instance. Security best practice: protect + mask secrets, use file variables for certificates/keys. Example: deploy: variables: REGION: us-east-1, script: [aws deploy --region $REGION]. GitLab 17 enhancement: CI/CD variable expressions support regex matching in rules.
Runners: agents executing CI/CD jobs on various platforms. In GitLab 17.x, runner types: shared (all projects), group (group-level), project-specific (single project). Executors: Shell, Docker, Kubernetes, Docker Autoscale (new), Instance executor. GitLab 17.5+ deprecates Docker Machine executor (removed v20.0), use GitLab Runner Autoscaler instead. Registration changed in GitLab 17.0: registration tokens disabled, use runner authentication tokens. GitLab-hosted: shared runners on GitLab.com (free tier: 400 CI/CD minutes/month). Self-hosted: install GitLab Runner binary on infrastructure. Configuration: tags for job selection (tags: [docker, linux]), concurrent jobs (default: 1, configurable). Kubernetes executor creates new Pod per job (scalable, cloud-native). GitLab 17.11+ improved runner management UI with job history and assigned projects view. Example: test: tags: [docker], image: node:20. Use shared for quick start, self-hosted for custom environments/compliance.
Script: required keyword containing shell commands executed by GitLab Runner. Syntax: script: [command1, command2] or multi-line script: - | for complex commands. In GitLab 17.x, scripts execute in runner's shell (bash/sh/powershell). Job lifecycle: before_script → script → after_script. Important: after_script executes in new shell, cannot access script variables/state. Exit codes: non-zero (1-255) fails job immediately unless allow_failure: true. GitLab 17 best practice: keep scripts minimal, call repository scripts for maintainability (script: [./scripts/build.sh]). Multi-line example: script: - | npm ci --prefer-offline npm run build npm test. Variables available: $CI_COMMIT_SHA, $CI_PROJECT_DIR, etc. Security: scripts run with runner user permissions. Example: test: before_script: [apt-get update], script: [./run-tests.sh], after_script: [./cleanup.sh].
Needs: creates Directed Acyclic Graph (DAG) pipelines in GitLab 17.x by executing jobs out-of-order, bypassing stage sequencing. Syntax: needs: [build_job, lint_job]. Without needs: jobs wait for entire previous stage completion. With needs: job starts immediately after specified dependencies complete, reducing pipeline duration by 40-80% for complex workflows. Benefits: faster feedback, flexible dependencies (fan-in/fan-out/diamond patterns), parallel execution. Limitations: max 50 needs per job (GitLab enforced). Artifacts automatically downloaded from needed jobs. GitLab 17 optimization: visualize DAG in Pipeline Editor for debugging. Example: test: needs: [build], script: [npm test] runs as soon as build completes, not waiting for entire build stage. Use cases: multi-platform builds, microservices deployments, OS builds with complex dependency graphs. Performance: complex pipelines see 50%+ time reduction vs sequential stages.
Cache: preserves files between jobs for speed optimization in GitLab 17.x (supports max 4 caches per job). Configuration: cache: { paths: [node_modules/], key: ${CI_COMMIT_REF_SLUG} }. Caches restore before artifacts during job setup. Cache keys: static (key: deps) or dynamic (key: ${CI_COMMIT_REF_SLUG}-${CI_PIPELINE_ID}). Policies: pull (download only, for read-only jobs), push (upload only, initial cache creation), pull-push (default, update cache). Multiple caches (GitLab 13.10+): cache: [{ key: gems, paths: [vendor/] }, { key: npm, paths: [node_modules/] }]. GitLab 17 best practices: (1) Use pull policy for test/build jobs (test: cache: { key: deps, paths: [node_modules/], policy: pull }). (2) Tag runners for cache consistency (tag: [shared-cache]). (3) Implement pull-and-push-if-changed pattern (delete cache folder if unchanged to skip upload). (4) Store in S3/distributed cache for multi-runner setups. Performance: reduces npm install from 60s to 10s with proper caching.
Environment: deployment target tracking in GitLab 17.x (production, staging, review apps). Define: environment: { name: production, url: https://example.com, deployment_tier: production }. Features: deployment history tracking, one-click rollbacks, environment-specific variables, deployment approvals. Dynamic environments for review apps: environment: { name: review/$CI_COMMIT_REF_SLUG, url: https://$CI_COMMIT_REF_SLUG.example.com, on_stop: stop_review, auto_stop_in: 1 day }. Protected environments (Settings > CI/CD): restrict deployment to authorized users/groups. Stop action: cleanup job (on_stop: stop_review) with when: manual and action: stop. GitLab 17 Auto DevOps deployment strategies: continuous, canary (incremental rollout), blue-green. View in Operations > Environments with deployment timeline, metrics, logs. Example: deploy: { stage: deploy, environment: { name: staging, url: https://staging.example.com }, script: [./deploy.sh staging] }. Use for: deployment tracking, review apps per MR, rollback capability.
Include: imports external YAML configurations in GitLab 17.x for DRY pipelines. Methods: (1) include:local (same repo: /templates/.gitlab-ci.yml). (2) include:project (cross-project: project/path, file: .gitlab-ci.yml, ref: main). (3) include:remote (public URLs: https://example.com/ci.yml). (4) include:template (GitLab official: Security/SAST.gitlab-ci.yml). (5) include:component (CI/CD Catalog: gitlab.com/org/[email protected], inputs: {}). GitLab 17.0+ component support with parameterized inputs. Configuration merges: included configs deep-merge with .gitlab-ci.yml, job-level overrides win. Example: include: [{ local: /templates/docker.yml }, { component: gitlab.com/security/[email protected] }]. GitLab 17 best practices: use components for versioned organization standards, templates for quick GitLab features (SAST/DAST), local includes for repo-specific templates. Security: audit external includes, pin component versions to SHA/release. Use for: multi-project consistency, security scanning, deployment workflows.
Services: Docker containers running alongside job for integration testing in GitLab 17.x. Requires Docker/Kubernetes executor. Define: services: [mysql:8.0, redis:7]. Use cases: database testing (PostgreSQL/MySQL/MongoDB), cache testing (Redis/Memcached), browser automation (Selenium), Docker-in-Docker builds. Service access: hostname = service name or alias. Example: integration_test: { image: node:20, services: [{ name: postgres:15, alias: db }], variables: { POSTGRES_PASSWORD: test }, script: [psql -h db -U postgres] }. Docker-in-Docker: test: { image: docker:24, services: [docker:24-dind], script: [docker build -t app .] }. GitLab 17 best practices: (1) Use specific image versions (mysql:8.0, not mysql:latest). (2) Pass config via variables (POSTGRES_DB: testdb). (3) Set aliases for clarity (alias: database). (4) Use healthchecks for service readiness. Services start before before_script, accessible during script execution. Performance: services add 10-30s startup time to jobs.
Workflow: controls pipeline-level execution in GitLab 17.x using workflow:rules. Purpose: prevent duplicate pipelines, enforce pipeline conditions, auto-cancel redundant runs. Syntax: workflow: { rules: [{ if: $CI_PIPELINE_SOURCE == 'merge_request_event' }] }. Common pattern (prevent duplicates): workflow: rules: [{ if: '$CI_PIPELINE_SOURCE == "merge_request_event"' }, { if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS', when: never }, { if: $CI_COMMIT_BRANCH }]. This runs MR pipelines when MR exists, branch pipelines otherwise. GitLab 17 features: (1) workflow:auto_cancel: { on_new_commit: interruptible } cancels redundant pipelines. (2) workflow:name for dynamic names. Use cases: skip draft MRs (if: '$CI_MERGE_REQUEST_TITLE =~ /^Draft:/'), schedule-only pipelines, protected-branch-only. Default behavior: pipeline runs for every push. Best practice: define workflow:rules globally to prevent duplicate MR+branch pipelines, saving CI minutes.
GitLab 17.x secrets management: (1) CI/CD variables with masked + protected flags (Settings > CI/CD > Variables). (2) File variables for certificates/keys. (3) External secrets via OIDC: HashiCorp Vault, AWS Secrets Manager, Azure Key Vault. Protected variables: accessible only on protected branches/tags. Masked variables: replaced with *** in job logs (regex validation required). File variables: value written to temp file, path in $VARIABLE. GitLab 17.0+ OIDC integration: id_tokens: { VAULT_TOKEN: { aud: vault.example.com } }, secrets: { DATABASE_PASSWORD: { vault: secret/data/production/db@password, token: $VAULT_TOKEN } }. Vault 1.17+ requires bound audiences for JWT auth. Best practices 2025: (1) Never hardcode secrets in .gitlab-ci.yml. (2) Use masked + protected for production secrets. (3) Rotate secrets regularly. (4) Use file variables for multi-line secrets (SSH keys, certs). (5) Prefer external secret managers for compliance. Example: deploy: script: [kubectl apply -f $KUBECONFIG_FILE] with KUBECONFIG_FILE as file variable.
Merge request (MR) pipelines run when MR is created/updated to test changes before merge. Configure with workflow: rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event'. Triggers: create MR, push to source branch, manual run. Runs on source branch only (ignores target). Prevent duplicates: workflow: rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event', - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS, when: never, - if: $CI_COMMIT_BRANCH. GitLab checks MR pipelines (not branch) when 'Pipelines must succeed' enabled. Use for: testing changes before merge, preview deployments, preventing broken main. Advanced: merge result pipelines, merge trains.
Templates: GitLab-maintained reusable YAML configurations for common CI/CD tasks. Include via: include: - template: Security/SAST.gitlab-ci.yml. GitLab 17.x official templates: (1) Security scanning (SAST, DAST, Secret Detection, Dependency Scanning, Container Scanning). (2) Auto-DevOps.gitlab-ci.yml (complete CI/CD pipeline). (3) Code-Quality.gitlab-ci.yml (linting/analysis). (4) Jobs/.gitlab-ci.yml (Build, Deploy, Test templates). Templates vs Components: templates are unversioned GitLab-maintained, components are versioned user/org-created (GitLab 17.0+). Custom templates: store in .gitlab-ci/.yml, include:local. Extends: inherit template jobs and override (my_job: { extends: .template_job, script: [custom] }). Hidden jobs (prefix with dot): use as templates. Example: include: - template: Security/SAST.gitlab-ci.yml enables SAST scanning. GitLab 17 recommendation: use official templates for quick start (security/Auto DevOps), migrate to components for customization/versioning. Find templates: GitLab repository lib/gitlab/ci/templates/.
Parallel: runs multiple job instances simultaneously in GitLab 17.x for distributed testing/builds. Syntax: parallel: 5 creates 5 identical job instances. Access instance info: CI_NODE_INDEX (1-5 index), CI_NODE_TOTAL (5 total). Matrix builds (GitLab 13.3+): parallel: { matrix: [{ PROVIDER: [aws, gcp], STACK: [eks, gke] }] } creates 4 jobs (aws/eks, aws/gke, gcp/eks, gcp/gke). Limitations: max 200 jobs per matrix (GitLab enforced). Use cases: (1) Test parallelization (split test suite: rspec --ci-node-index $CI_NODE_INDEX --ci-node-total $CI_NODE_TOTAL). (2) Multi-platform builds (OS: [linux, windows, macos]). (3) Multi-environment deployments. Performance: reduces test suite from 20min to 4min with parallel: 5 (80% faster). GitLab 17 best practice: combine with needs for DAG optimization. Example: test: { parallel: 3, script: [npm test -- --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL] }. Note: consumes more CI minutes but increases productivity.
GitLab 17.x best practices for production pipelines: (1) Validate YAML: use CI Lint (CI/CD > Editor > Validate) before commit. (2) Configuration reuse: use components (include: - component: gitlab.com/org/[email protected]) for versioned configs, templates for quick starts. (3) Rules over only/except: rules: [{ if: $CI_PIPELINE_SOURCE == 'merge_request_event' }] for precise control. (4) Caching optimization: cache dependencies with pull policy for read-only jobs, max 4 caches per job. (5) DAG pipelines: use needs for 40-80% faster pipelines. (6) Security: masked + protected variables, OIDC for external secrets (Vault/AWS). (7) Maintainability: minimal scripts in YAML, call repo scripts (script: [./scripts/deploy.sh]). (8) DRY principle: use extends for job templates. (9) Prevent duplicates: workflow:rules to avoid MR+branch duplicate pipelines. (10) Manual production deploys: when: manual + allow_failure: false. (11) Review apps: dynamic environments per MR. (12) Runner tagging: consistent cache sharing. 2025 additions: pin component versions to SHA, use Auto DevOps deployment strategies (canary/blue-green), implement workflow:auto_cancel.
GitLab 17.x debugging methods: (1) CI Lint (CI/CD > Editor > Validate): validate YAML syntax, simulate pipeline. (2) Pipeline Editor: visual DAG preview, YAML validation. (3) Job logs: detailed execution logs with timestamps, exit codes. (4) CI_DEBUG_TRACE: enable verbose logging (set CI_DEBUG_TRACE=true variable, shows all commands, WARNING: may expose secrets). (5) Artifacts: save debug files (logs, core dumps) for inspection. (6) Local execution: gitlab-runner exec docker job_name (limited, deprecated GitLab 15.7+). (7) echo/set -x: add debug prints in scripts. GitLab 17 tools: Pipeline Graph shows job dependencies, Failed Jobs tab filters failures. Common issues: (1) YAML syntax errors → use CI Lint. (2) Missing artifacts → check dependencies/needs. (3) Cache misses → verify cache keys, runner tags. (4) Job not running → check rules/workflow:rules. (5) Runner unavailable → verify tags. Example debug job: debug: { script: [env, pwd, ls -la], when: on_failure, artifacts: { paths: [logs/], when: always } }. GitLab 17.11+ improved job logs with collapsible sections.
allow_failure: permits job failures without blocking pipeline in GitLab 17.x. Default: false (job failure fails pipeline), true for manual jobs (when: manual defaults to allow_failure: true). Syntax: allow_failure: true or allow_failure: { exit_codes: [137, 255] } for specific exit codes. Job execution: job runs and completes, but failure doesn't block downstream stages/jobs. UI: failed jobs with allow_failure show warning icon (⚠️), not error (❌). Use cases: (1) Experimental features (allow_failure: true). (2) Non-critical tests (code quality, performance). (3) Manual approval gates: set allow_failure: false for blocking manual jobs (when: manual, allow_failure: false pauses pipeline). (4) Flaky tests (temporary, fix root cause). (5) Exit code handling: allow_failure: { exit_codes: 137 } allows OOM failures. GitLab 17 best practice: use sparingly, don't abuse for masking real failures. Critical tests (security, unit tests) should always fail pipeline (allow_failure: false). Example: code_quality: { script: [./lint.sh], allow_failure: true } keeps pipeline green with warnings.
Components: reusable pipeline configurations with versioning, GA in GitLab 17.0, discoverable via CI/CD Catalog at gitlab.com/explore/catalog. Format:
GitLab 17 comparison of Components vs Templates: (1) Versioning: Components use SemVer (@1.0.0, @2.1.3) with immutable releases, Templates are unversioned GitLab-maintained files. (2) Source: Components from any GitLab project (gitlab.com/org/component), Templates from GitLab's official library. (3) Discoverability: Components in CI/CD Catalog (gitlab.com/explore/catalog), Templates in documentation only. (4) Inputs: Components support parameterized inputs (environment, region, timeout), Templates are static. (5) Security: Components support SHA256 integrity verification, Templates rely on GitLab trust. (6) Interpolation: Components use $[[ inputs.name ]], Templates none. Template syntax: include: - template: Security/SAST.gitlab-ci.yml (GitLab-maintained). Component syntax: include: - component: gitlab.com/security/[email protected], inputs: { severity: high } (custom/community). GitLab 17 recommendation: use Templates for quick start (Auto DevOps, security scans), Components for organization-specific production workflows with versioning.
Use when: manual with allow_failure: false to create blocking manual deployment gates. Configuration: deploy_prod: stage: deploy, environment: { name: production, url: https://prod.example.com }, when: manual, allow_failure: false, script: [./deploy.sh]. Setting allow_failure: false makes the job blocking, pausing the pipeline until an authorized user clicks the play button. Combine with protected environments (Settings > CI/CD > Protected Environments) to restrict who can approve deployments. Use for: production deployments requiring human approval, compliance requirements, critical releases. Manual jobs show orange play button in pipeline view.
Use dynamic environment names with $CI_COMMIT_REF_NAME for branch-based review apps. Configuration: review: stage: deploy, environment: { name: review/$CI_COMMIT_REF_NAME, url: https://$CI_COMMIT_REF_SLUG.review.example.com, on_stop: stop_review }, script: [./deploy-review.sh], rules: [{ if: '$CI_PIPELINE_SOURCE == "merge_request_event"' }]. Create stop action: stop_review: stage: deploy, environment: { name: review/$CI_COMMIT_REF_NAME, action: stop }, when: manual, script: [./cleanup-review.sh]. Each MR gets isolated environment. Review apps automatically appear in GitLab Environments page with deployment history and stop button.
Deploy to inactive environment (green), test, then switch traffic from active (blue). Configuration: deploy_green: stage: deploy, environment: { name: production-green }, script: [./deploy.sh green], when: manual. test_green: stage: test, dependencies: [deploy_green], script: [./smoke-test.sh green]. switch_traffic: stage: switch, environment: { name: production }, script: [./switch-traffic.sh blue green], when: manual, allow_failure: false. Requires infrastructure supporting dual environments and traffic switching (load balancer, DNS, or service mesh). Keep blue environment for instant rollback. GitLab shows both environments in Operations > Environments.
Use GitLab's incremental rollout feature for Kubernetes canary deployments. Configuration: deploy_canary: stage: deploy, environment: { name: production }, script: [./deploy.sh], resource_group: production. Enable in Settings > CI/CD > Auto DevOps > Deployment strategy: 'Timed incremental rollout'. Alternatively, manual percentage-based rollout: deploy_10: script: [./deploy.sh 10%], when: manual. deploy_50: script: [./deploy.sh 50%], when: manual. deploy_100: script: [./deploy.sh 100%], when: manual. Monitor metrics between stages. GitLab Auto DevOps uses 5-minute intervals by default (configure with AUTO_DEPLOY_WAIT_TIME variable). Requires Kubernetes with traffic splitting support.
GitLab Auto DevOps offers three deployment strategies (Settings > CI/CD > Auto DevOps > Deployment strategy): (1) Continuous deployment to production - Automatic deploy to production on main branch commits. (2) Timed incremental rollout - Gradual traffic shift with 5-minute intervals (configure with AUTO_DEPLOY_WAIT_TIME variable), sets INCREMENTAL_ROLLOUT_MODE: timed. (3) Automatic deployment to staging, manual to production - Sets STAGING_ENABLED: 1 and INCREMENTAL_ROLLOUT_MODE: manual. Auto DevOps requires base domain configured and Kubernetes cluster connected. Choose strategy before enabling Auto DevOps to avoid deployment failures.
GitLab 17.x anti-patterns causing slow/expensive/insecure pipelines: (1) No caching: rebuilds dependencies every run (use cache: { paths: [node_modules/], key: deps }). (2) Large artifacts without expiration: wastes storage (set expire_in: 1 week). (3) Complex inline scripts: unmaintainable (use script: [./scripts/build.sh] instead). (4) only/except syntax: deprecated in GitLab 17 (use rules instead). (5) Hardcoded secrets: security risk (use masked + protected variables). (6) No stage organization: unclear workflow (define logical stages). (7) Sequential stages only: slow (use needs for DAG, 40-80% faster). (8) Ignoring CI Lint: syntax errors in production. (9) Excessive parallel jobs: hits 200 job limit, wastes runners. (10) No workflow:rules: duplicate MR+branch pipelines waste CI minutes. (11) Using latest image tags: non-reproducible builds (pin to node:20.11). (12) Not using components: duplicated configs across projects. GitLab 17 best practices: cache dependencies, set artifact expiration, use DAG pipelines, implement workflow:rules, pin versions, audit with CI Lint. Performance: proper caching + needs reduces pipeline from 30min to 8min.