Problem Statement
Explain GitLab CI/CD architecture and .gitlab-ci.yml syntax in detail. Include stages, jobs, artifacts, cache, dependencies, and advanced features.
Explanation
GitLab CI/CD YAML structure starts with defining stages (pipeline phases). Stages run sequentially, jobs within stages run in parallel. Default stages are build, test, deploy but custom stages can be defined:
```yaml
stages:
- build
- test
- security
- deploy
- cleanup
```
Jobs are tasks within stages. Job definition includes stage assignment, script (commands to run), and optional directives:
```yaml
build_app:
stage: build
image: node:18
script:
- npm install
- npm run build
artifacts:
paths:
- dist/
expire_in: 1 week
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
only:
- main
- merge_requests
```
Artifacts are files generated by jobs passed to subsequent jobs or downloadable after pipeline completes. artifacts keyword specifies paths to preserve. Artifacts persist between stages allowing test stage to use build stage outputs. Example: build job creates dist/ directory, test job uses it:
```yaml
test_app:
stage: test
dependencies:
- build_app
script:
- npm test
```
Cache speeds up jobs by storing dependencies between pipeline runs. Unlike artifacts (passed between jobs in same pipeline), cache persists across pipelines. Cache key determines cache uniqueness, typically using branch name or lock file hash:
```yaml
cache:
key:
files:
- package-lock.json
paths:
- node_modules/
```
Dependencies specify which jobs' artifacts this job needs. Without dependencies, job receives all previous stage artifacts. With dependencies: [job1, job2], only specified artifacts are available.
Variables define environment variables:
```yaml
variables:
DATABASE_URL: "postgres://localhost/db"
DEPLOY_ENV: "staging"
job:
script:
- echo $DATABASE_URL
```
GitLab provides predefined variables (CI_COMMIT_SHA, CI_PIPELINE_ID, CI_COMMIT_BRANCH).
Rules provide advanced conditional execution:
```yaml
job:
script: echo "Deploy"
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: never
- if: '$CI_COMMIT_BRANCH == "main"'
when: on_success
- when: manual
```
Before_script and after_script run before/after main script:
```yaml
job:
before_script:
- echo "Setup"
script:
- echo "Main task"
after_script:
- echo "Cleanup"
```
Services provide additional containers for job (databases, caches):
```yaml
test:
image: node:18
services:
- postgres:13
variables:
POSTGRES_DB: testdb
script:
- npm test
```
Includes enable reusing configuration:
```yaml
include:
- local: '.gitlab-ci-templates.yml'
- project: 'group/project'
file: '/templates/ci.yml'
- remote: 'https://example.com/ci-template.yml'
```
Extends inherits configuration from templates:
```yaml
.deploy_template:
script:
- ./deploy.sh
only:
- main
deploy_staging:
extends: .deploy_template
variables:
ENVIRONMENT: staging
deploy_prod:
extends: .deploy_template
variables:
ENVIRONMENT: production
```
Triggers for multi-project pipelines:
```yaml
trigger_downstream:
stage: deploy
trigger:
project: group/downstream-project
branch: main
```
Understanding GitLab CI/CD YAML syntax enables building sophisticated pipelines with proper dependency management, caching strategies, and modular configuration.