Initial commit
This commit is contained in:
939
skills/gitlab/references/ci-cd.md
Normal file
939
skills/gitlab/references/ci-cd.md
Normal file
@@ -0,0 +1,939 @@
|
||||
# GitLab CI/CD Reference
|
||||
|
||||
## Overview
|
||||
|
||||
GitLab CI/CD is a built-in continuous integration and deployment tool. Pipelines are defined using `.gitlab-ci.yml` files in the repository root.
|
||||
|
||||
## .gitlab-ci.yml Structure
|
||||
|
||||
### Basic Example
|
||||
|
||||
```yaml
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- deploy
|
||||
|
||||
build-job:
|
||||
stage: build
|
||||
script:
|
||||
- echo "Building the application..."
|
||||
- npm install
|
||||
- npm run build
|
||||
artifacts:
|
||||
paths:
|
||||
- dist/
|
||||
|
||||
test-job:
|
||||
stage: test
|
||||
script:
|
||||
- echo "Running tests..."
|
||||
- npm test
|
||||
|
||||
deploy-job:
|
||||
stage: deploy
|
||||
script:
|
||||
- echo "Deploying application..."
|
||||
- ./deploy.sh
|
||||
environment:
|
||||
name: production
|
||||
only:
|
||||
- main
|
||||
```
|
||||
|
||||
## Pipeline Configuration
|
||||
|
||||
### Stages
|
||||
|
||||
Define pipeline stages (executed in order):
|
||||
|
||||
```yaml
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- deploy
|
||||
- release
|
||||
```
|
||||
|
||||
**Default stages** (if not specified):
|
||||
```yaml
|
||||
stages:
|
||||
- .pre
|
||||
- build
|
||||
- test
|
||||
- deploy
|
||||
- .post
|
||||
```
|
||||
|
||||
### Jobs
|
||||
|
||||
Jobs define what to execute:
|
||||
|
||||
```yaml
|
||||
job-name:
|
||||
stage: test
|
||||
script:
|
||||
- echo "Running job"
|
||||
tags:
|
||||
- docker
|
||||
only:
|
||||
- main
|
||||
```
|
||||
|
||||
### Script
|
||||
|
||||
Commands to execute:
|
||||
|
||||
```yaml
|
||||
script:
|
||||
- echo "Single command"
|
||||
|
||||
# Or multi-line
|
||||
script:
|
||||
- echo "First command"
|
||||
- echo "Second command"
|
||||
- |
|
||||
echo "Multi-line script"
|
||||
for i in {1..5}; do
|
||||
echo "Line $i"
|
||||
done
|
||||
```
|
||||
|
||||
### before_script and after_script
|
||||
|
||||
```yaml
|
||||
before_script:
|
||||
- echo "Executed before every job"
|
||||
|
||||
after_script:
|
||||
- echo "Executed after every job"
|
||||
|
||||
job-name:
|
||||
before_script:
|
||||
- echo "Job-specific before script"
|
||||
script:
|
||||
- echo "Main script"
|
||||
after_script:
|
||||
- echo "Job-specific after script"
|
||||
```
|
||||
|
||||
## Images and Services
|
||||
|
||||
### Docker Image
|
||||
|
||||
```yaml
|
||||
image: node:18
|
||||
|
||||
# Job-specific image
|
||||
job-name:
|
||||
image: python:3.11
|
||||
script:
|
||||
- python --version
|
||||
```
|
||||
|
||||
### Services (Docker-in-Docker, databases, etc.)
|
||||
|
||||
```yaml
|
||||
services:
|
||||
- docker:dind
|
||||
- postgres:14
|
||||
|
||||
variables:
|
||||
POSTGRES_DB: test_db
|
||||
POSTGRES_USER: user
|
||||
POSTGRES_PASSWORD: password
|
||||
```
|
||||
|
||||
## Variables
|
||||
|
||||
### Global Variables
|
||||
|
||||
```yaml
|
||||
variables:
|
||||
ENVIRONMENT: "production"
|
||||
API_URL: "https://api.example.com"
|
||||
```
|
||||
|
||||
### Job Variables
|
||||
|
||||
```yaml
|
||||
job-name:
|
||||
variables:
|
||||
JOB_VARIABLE: "value"
|
||||
script:
|
||||
- echo $JOB_VARIABLE
|
||||
```
|
||||
|
||||
### Predefined Variables
|
||||
|
||||
Common CI/CD variables:
|
||||
|
||||
- `CI`: Always `true` in CI
|
||||
- `CI_COMMIT_SHA`: Commit SHA
|
||||
- `CI_COMMIT_REF_NAME`: Branch or tag name
|
||||
- `CI_COMMIT_BRANCH`: Branch name
|
||||
- `CI_COMMIT_TAG`: Tag name
|
||||
- `CI_PROJECT_ID`: Project ID
|
||||
- `CI_PROJECT_NAME`: Project name
|
||||
- `CI_PROJECT_PATH`: Project path
|
||||
- `CI_PIPELINE_ID`: Pipeline ID
|
||||
- `CI_PIPELINE_IID`: Pipeline IID
|
||||
- `CI_JOB_ID`: Job ID
|
||||
- `CI_JOB_NAME`: Job name
|
||||
- `CI_JOB_STAGE`: Job stage
|
||||
- `CI_REGISTRY`: GitLab container registry
|
||||
- `CI_REGISTRY_IMAGE`: Full registry path
|
||||
- `CI_REGISTRY_USER`: Registry username
|
||||
- `CI_REGISTRY_PASSWORD`: Registry password
|
||||
- `GITLAB_USER_EMAIL`: User email
|
||||
- `GITLAB_USER_LOGIN`: User username
|
||||
|
||||
### Variable Precedence
|
||||
|
||||
(Highest to lowest priority)
|
||||
1. Trigger variables, scheduled pipeline variables, manual pipeline run variables
|
||||
2. Project variables
|
||||
3. Group variables
|
||||
4. Instance variables
|
||||
5. Variables in .gitlab-ci.yml
|
||||
6. Predefined variables
|
||||
|
||||
## Artifacts
|
||||
|
||||
### Basic Artifacts
|
||||
|
||||
```yaml
|
||||
job-name:
|
||||
script:
|
||||
- npm run build
|
||||
artifacts:
|
||||
paths:
|
||||
- dist/
|
||||
- build/
|
||||
expire_in: 1 week
|
||||
```
|
||||
|
||||
### Artifact Options
|
||||
|
||||
```yaml
|
||||
artifacts:
|
||||
# Files to include
|
||||
paths:
|
||||
- dist/
|
||||
- "*.log"
|
||||
|
||||
# Files to exclude
|
||||
exclude:
|
||||
- dist/*.md
|
||||
|
||||
# Expiration time
|
||||
expire_in: 30 days # default: 30 days
|
||||
# Options: 1 day, 1 week, 1 month, never
|
||||
|
||||
# When to upload artifacts
|
||||
when: always # on_success (default), on_failure, always
|
||||
|
||||
# Artifact name
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
|
||||
|
||||
# Make artifacts public
|
||||
public: true
|
||||
|
||||
# Untracked files
|
||||
untracked: false
|
||||
|
||||
# Reports
|
||||
reports:
|
||||
junit: test-results.xml
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: coverage.xml
|
||||
```
|
||||
|
||||
### Artifact Reports
|
||||
|
||||
```yaml
|
||||
test-job:
|
||||
script:
|
||||
- npm test
|
||||
artifacts:
|
||||
reports:
|
||||
junit: test-results.xml
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: coverage.xml
|
||||
dotenv: build.env
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
|
||||
```yaml
|
||||
build-job:
|
||||
script:
|
||||
- npm run build
|
||||
artifacts:
|
||||
paths:
|
||||
- dist/
|
||||
|
||||
deploy-job:
|
||||
dependencies:
|
||||
- build-job
|
||||
script:
|
||||
- ls -la dist/
|
||||
```
|
||||
|
||||
### Needs (DAG Pipelines)
|
||||
|
||||
```yaml
|
||||
build-job:
|
||||
stage: build
|
||||
script:
|
||||
- npm run build
|
||||
artifacts:
|
||||
paths:
|
||||
- dist/
|
||||
|
||||
test-job:
|
||||
stage: test
|
||||
needs: [build-job]
|
||||
script:
|
||||
- npm test
|
||||
|
||||
deploy-job:
|
||||
stage: deploy
|
||||
needs: [test-job]
|
||||
script:
|
||||
- ./deploy.sh
|
||||
```
|
||||
|
||||
## Caching
|
||||
|
||||
### Cache Configuration
|
||||
|
||||
```yaml
|
||||
cache:
|
||||
paths:
|
||||
- node_modules/
|
||||
- .npm/
|
||||
|
||||
# Job-specific cache
|
||||
job-name:
|
||||
cache:
|
||||
key: "$CI_COMMIT_REF_NAME"
|
||||
paths:
|
||||
- vendor/
|
||||
policy: pull-push # pull-push (default), pull, push
|
||||
```
|
||||
|
||||
### Cache Keys
|
||||
|
||||
```yaml
|
||||
# Static key
|
||||
cache:
|
||||
key: my-cache
|
||||
|
||||
# Dynamic key based on branch
|
||||
cache:
|
||||
key: "$CI_COMMIT_REF_NAME"
|
||||
|
||||
# Key with files
|
||||
cache:
|
||||
key:
|
||||
files:
|
||||
- package-lock.json
|
||||
prefix: npm-cache
|
||||
|
||||
# Multiple caches
|
||||
cache:
|
||||
- key: npm-cache
|
||||
paths:
|
||||
- node_modules/
|
||||
- key: build-cache
|
||||
paths:
|
||||
- dist/
|
||||
```
|
||||
|
||||
### Cache vs Artifacts
|
||||
|
||||
**Use Cache for**:
|
||||
- Dependencies (node_modules, vendor)
|
||||
- Compiled libraries
|
||||
- Downloaded packages
|
||||
|
||||
**Use Artifacts for**:
|
||||
- Build output
|
||||
- Test results
|
||||
- Files needed in later stages
|
||||
|
||||
## Job Control
|
||||
|
||||
### Rules
|
||||
|
||||
```yaml
|
||||
job-name:
|
||||
script:
|
||||
- echo "Running job"
|
||||
rules:
|
||||
# Run on main branch
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
when: always
|
||||
|
||||
# Run on merge requests
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
|
||||
# Run if file exists
|
||||
- exists:
|
||||
- Dockerfile
|
||||
when: manual
|
||||
|
||||
# Run if files changed
|
||||
- changes:
|
||||
- src/**/*.js
|
||||
- package.json
|
||||
|
||||
# Default
|
||||
- when: never
|
||||
```
|
||||
|
||||
### Only/Except (Legacy)
|
||||
|
||||
```yaml
|
||||
job-name:
|
||||
only:
|
||||
- main
|
||||
- tags
|
||||
- merge_requests
|
||||
except:
|
||||
- schedules
|
||||
```
|
||||
|
||||
### When
|
||||
|
||||
```yaml
|
||||
job-name:
|
||||
when: manual # on_success (default), on_failure, always, manual, delayed, never
|
||||
|
||||
# Delayed job
|
||||
job-delayed:
|
||||
when: delayed
|
||||
start_in: 30 minutes
|
||||
```
|
||||
|
||||
### Allow Failure
|
||||
|
||||
```yaml
|
||||
job-name:
|
||||
allow_failure: true
|
||||
script:
|
||||
- ./optional-script.sh
|
||||
|
||||
# Conditional failure
|
||||
job-conditional:
|
||||
allow_failure:
|
||||
exit_codes:
|
||||
- 137 # Specific exit code
|
||||
- 139
|
||||
```
|
||||
|
||||
## Environments
|
||||
|
||||
### Basic Environment
|
||||
|
||||
```yaml
|
||||
deploy-production:
|
||||
stage: deploy
|
||||
script:
|
||||
- ./deploy.sh
|
||||
environment:
|
||||
name: production
|
||||
url: https://prod.example.com
|
||||
```
|
||||
|
||||
### Dynamic Environments
|
||||
|
||||
```yaml
|
||||
deploy-review:
|
||||
stage: deploy
|
||||
script:
|
||||
- ./deploy-review.sh
|
||||
environment:
|
||||
name: review/$CI_COMMIT_REF_NAME
|
||||
url: https://$CI_COMMIT_REF_SLUG.review.example.com
|
||||
on_stop: stop-review
|
||||
only:
|
||||
- branches
|
||||
except:
|
||||
- main
|
||||
|
||||
stop-review:
|
||||
stage: deploy
|
||||
script:
|
||||
- ./stop-review.sh
|
||||
environment:
|
||||
name: review/$CI_COMMIT_REF_NAME
|
||||
action: stop
|
||||
when: manual
|
||||
```
|
||||
|
||||
### Environment Tiers
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
name: production
|
||||
deployment_tier: production # production, staging, testing, development, other
|
||||
```
|
||||
|
||||
## Includes
|
||||
|
||||
### Include External Files
|
||||
|
||||
```yaml
|
||||
include:
|
||||
# Include from same project
|
||||
- local: '/templates/.gitlab-ci-template.yml'
|
||||
|
||||
# Include from another project
|
||||
- project: 'group/project'
|
||||
ref: main
|
||||
file: '/templates/.gitlab-ci.yml'
|
||||
|
||||
# Include from URL
|
||||
- remote: 'https://example.com/.gitlab-ci.yml'
|
||||
|
||||
# Include template
|
||||
- template: Auto-DevOps.gitlab-ci.yml
|
||||
```
|
||||
|
||||
### Include with Rules
|
||||
|
||||
```yaml
|
||||
include:
|
||||
- local: '/templates/docker.yml'
|
||||
rules:
|
||||
- if: $DOCKER_ENABLED == "true"
|
||||
```
|
||||
|
||||
## Extends
|
||||
|
||||
### Template Jobs
|
||||
|
||||
```yaml
|
||||
.deploy-template:
|
||||
script:
|
||||
- ./deploy.sh
|
||||
only:
|
||||
- main
|
||||
|
||||
deploy-staging:
|
||||
extends: .deploy-template
|
||||
variables:
|
||||
ENVIRONMENT: staging
|
||||
|
||||
deploy-production:
|
||||
extends: .deploy-template
|
||||
variables:
|
||||
ENVIRONMENT: production
|
||||
when: manual
|
||||
```
|
||||
|
||||
## Parallel Jobs
|
||||
|
||||
### Matrix
|
||||
|
||||
```yaml
|
||||
test:
|
||||
parallel:
|
||||
matrix:
|
||||
- NODE_VERSION: ["14", "16", "18"]
|
||||
OS: ["linux", "windows"]
|
||||
script:
|
||||
- node --version
|
||||
- echo "Testing on $OS with Node $NODE_VERSION"
|
||||
```
|
||||
|
||||
### Simple Parallel
|
||||
|
||||
```yaml
|
||||
test:
|
||||
parallel: 5
|
||||
script:
|
||||
- echo "Running test $CI_NODE_INDEX of $CI_NODE_TOTAL"
|
||||
```
|
||||
|
||||
## Triggers
|
||||
|
||||
### Multi-Project Pipelines
|
||||
|
||||
```yaml
|
||||
trigger-downstream:
|
||||
trigger:
|
||||
project: group/downstream-project
|
||||
branch: main
|
||||
strategy: depend # Wait for downstream pipeline
|
||||
```
|
||||
|
||||
### Parent-Child Pipelines
|
||||
|
||||
```yaml
|
||||
trigger-child:
|
||||
trigger:
|
||||
include: path/to/child-pipeline.yml
|
||||
strategy: depend
|
||||
```
|
||||
|
||||
## Docker
|
||||
|
||||
### Building Docker Images
|
||||
|
||||
```yaml
|
||||
build-image:
|
||||
image: docker:latest
|
||||
services:
|
||||
- docker:dind
|
||||
variables:
|
||||
DOCKER_TLS_CERTDIR: "/certs"
|
||||
script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
|
||||
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
```
|
||||
|
||||
### GitLab Container Registry
|
||||
|
||||
```yaml
|
||||
build-and-push:
|
||||
stage: build
|
||||
image: docker:latest
|
||||
services:
|
||||
- docker:dind
|
||||
script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG .
|
||||
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG $CI_REGISTRY_IMAGE:latest
|
||||
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
|
||||
- docker push $CI_REGISTRY_IMAGE:latest
|
||||
```
|
||||
|
||||
## Security Scanning
|
||||
|
||||
### SAST (Static Application Security Testing)
|
||||
|
||||
```yaml
|
||||
include:
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
```
|
||||
|
||||
### Dependency Scanning
|
||||
|
||||
```yaml
|
||||
include:
|
||||
- template: Security/Dependency-Scanning.gitlab-ci.yml
|
||||
```
|
||||
|
||||
### Container Scanning
|
||||
|
||||
```yaml
|
||||
include:
|
||||
- template: Security/Container-Scanning.gitlab-ci.yml
|
||||
|
||||
container_scanning:
|
||||
variables:
|
||||
CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE
|
||||
CI_APPLICATION_TAG: $CI_COMMIT_SHA
|
||||
```
|
||||
|
||||
### Secret Detection
|
||||
|
||||
```yaml
|
||||
include:
|
||||
- template: Security/Secret-Detection.gitlab-ci.yml
|
||||
```
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Retry
|
||||
|
||||
```yaml
|
||||
job-name:
|
||||
retry: 2 # Retry up to 2 times
|
||||
|
||||
# Conditional retry
|
||||
job-conditional:
|
||||
retry:
|
||||
max: 2
|
||||
when:
|
||||
- runner_system_failure
|
||||
- stuck_or_timeout_failure
|
||||
```
|
||||
|
||||
### Timeout
|
||||
|
||||
```yaml
|
||||
job-name:
|
||||
timeout: 3 hours # Default: 1 hour, Max: configured by admin
|
||||
```
|
||||
|
||||
### Resource Group
|
||||
|
||||
```yaml
|
||||
deploy-production:
|
||||
resource_group: production
|
||||
script:
|
||||
- ./deploy.sh
|
||||
```
|
||||
|
||||
### Coverage
|
||||
|
||||
```yaml
|
||||
test-job:
|
||||
script:
|
||||
- npm test
|
||||
coverage: '/Coverage: \d+\.\d+%/'
|
||||
```
|
||||
|
||||
## Pipeline Types
|
||||
|
||||
### Merge Request Pipelines
|
||||
|
||||
```yaml
|
||||
workflow:
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
```
|
||||
|
||||
### Scheduled Pipelines
|
||||
|
||||
```yaml
|
||||
job-name:
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||
script:
|
||||
- ./nightly-build.sh
|
||||
```
|
||||
|
||||
### Multi-Branch Pipelines
|
||||
|
||||
```yaml
|
||||
workflow:
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
|
||||
build-job:
|
||||
script:
|
||||
- echo "Building for branch: $CI_COMMIT_BRANCH"
|
||||
```
|
||||
|
||||
## Complete Example
|
||||
|
||||
```yaml
|
||||
# Define Docker image
|
||||
image: node:18
|
||||
|
||||
# Define stages
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- security
|
||||
- deploy
|
||||
|
||||
# Global variables
|
||||
variables:
|
||||
NODE_ENV: production
|
||||
CACHE_KEY: "$CI_COMMIT_REF_SLUG"
|
||||
|
||||
# Global cache
|
||||
cache:
|
||||
key: $CACHE_KEY
|
||||
paths:
|
||||
- node_modules/
|
||||
- .npm/
|
||||
|
||||
# Global before script
|
||||
before_script:
|
||||
- npm ci --cache .npm --prefer-offline
|
||||
|
||||
# Build job
|
||||
build:
|
||||
stage: build
|
||||
script:
|
||||
- npm run build
|
||||
artifacts:
|
||||
paths:
|
||||
- dist/
|
||||
expire_in: 1 week
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
|
||||
# Unit tests
|
||||
unit-tests:
|
||||
stage: test
|
||||
script:
|
||||
- npm run test:unit
|
||||
coverage: '/Lines\s+:\s+(\d+\.\d+)%/'
|
||||
artifacts:
|
||||
reports:
|
||||
junit: test-results.xml
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: coverage.xml
|
||||
|
||||
# Integration tests
|
||||
integration-tests:
|
||||
stage: test
|
||||
services:
|
||||
- postgres:14
|
||||
variables:
|
||||
POSTGRES_DB: test_db
|
||||
POSTGRES_USER: test_user
|
||||
POSTGRES_PASSWORD: test_password
|
||||
script:
|
||||
- npm run test:integration
|
||||
|
||||
# SAST scanning
|
||||
sast:
|
||||
stage: security
|
||||
include:
|
||||
- template: Security/SAST.gitlab-ci.yml
|
||||
|
||||
# Dependency scanning
|
||||
dependency_scanning:
|
||||
stage: security
|
||||
include:
|
||||
- template: Security/Dependency-Scanning.gitlab-ci.yml
|
||||
|
||||
# Build Docker image
|
||||
docker-build:
|
||||
stage: build
|
||||
image: docker:latest
|
||||
services:
|
||||
- docker:dind
|
||||
script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
|
||||
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA $CI_REGISTRY_IMAGE:latest
|
||||
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
|
||||
- docker push $CI_REGISTRY_IMAGE:latest
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
|
||||
# Deploy to staging
|
||||
deploy-staging:
|
||||
stage: deploy
|
||||
script:
|
||||
- echo "Deploying to staging..."
|
||||
- ./deploy.sh staging
|
||||
environment:
|
||||
name: staging
|
||||
url: https://staging.example.com
|
||||
deployment_tier: staging
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
|
||||
# Deploy to production
|
||||
deploy-production:
|
||||
stage: deploy
|
||||
script:
|
||||
- echo "Deploying to production..."
|
||||
- ./deploy.sh production
|
||||
environment:
|
||||
name: production
|
||||
url: https://example.com
|
||||
deployment_tier: production
|
||||
when: manual
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Pipeline Efficiency
|
||||
|
||||
- **Use caching**: Cache dependencies to speed up builds
|
||||
- **Parallel jobs**: Run independent jobs in parallel
|
||||
- **Artifacts**: Only include necessary files
|
||||
- **DAG pipelines**: Use `needs` to avoid waiting for entire stages
|
||||
|
||||
### 2. Security
|
||||
|
||||
- **Protected variables**: Use protected variables for secrets
|
||||
- **Masked variables**: Mask sensitive values in logs
|
||||
- **Security scanning**: Include SAST, dependency scanning, etc.
|
||||
- **Least privilege**: Give jobs minimum necessary permissions
|
||||
|
||||
### 3. Reliability
|
||||
|
||||
- **Retry failed jobs**: Configure retry for flaky tests
|
||||
- **Timeouts**: Set appropriate timeouts
|
||||
- **Failure handling**: Use `allow_failure` for optional jobs
|
||||
- **Health checks**: Test deployments after deployment
|
||||
|
||||
### 4. Maintainability
|
||||
|
||||
- **DRY principle**: Use extends and templates
|
||||
- **Includes**: Separate common configuration
|
||||
- **Documentation**: Comment complex configurations
|
||||
- **Consistent naming**: Use clear, consistent job names
|
||||
|
||||
### 5. Testing
|
||||
|
||||
- **Test early**: Run fast tests first
|
||||
- **Parallel testing**: Split test suites
|
||||
- **Test coverage**: Track and enforce coverage
|
||||
- **Multiple environments**: Test on different OS/versions
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Job stuck in pending**
|
||||
- Check runner availability
|
||||
- Verify runner tags match job tags
|
||||
- Check runner capacity
|
||||
|
||||
2. **Cache not working**
|
||||
- Verify cache key
|
||||
- Check cache path
|
||||
- Ensure runner has cache configured
|
||||
|
||||
3. **Artifacts not available**
|
||||
- Check artifact expiration
|
||||
- Verify artifact paths
|
||||
- Ensure job completed successfully
|
||||
|
||||
4. **Variables not expanding**
|
||||
- Check variable syntax ($VARIABLE or ${VARIABLE})
|
||||
- Verify variable scope (global, job, protected)
|
||||
- Check variable precedence
|
||||
|
||||
5. **Docker issues**
|
||||
- Verify docker:dind service is running
|
||||
- Check Docker TLS configuration
|
||||
- Ensure sufficient disk space
|
||||
|
||||
### Debugging
|
||||
|
||||
```yaml
|
||||
debug-job:
|
||||
script:
|
||||
# Print all environment variables
|
||||
- env | sort
|
||||
|
||||
# Print specific variables
|
||||
- echo $CI_COMMIT_SHA
|
||||
- echo $CI_PIPELINE_ID
|
||||
|
||||
# Print working directory
|
||||
- pwd
|
||||
- ls -la
|
||||
|
||||
# Check cache
|
||||
- ls -la node_modules/ || echo "Cache not present"
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- Official Documentation: https://docs.gitlab.com/ee/ci/
|
||||
- CI/CD Examples: https://docs.gitlab.com/ee/ci/examples/
|
||||
- Pipeline Configuration Reference: https://docs.gitlab.com/ee/ci/yaml/
|
||||
- GitLab CI/CD Templates: https://gitlab.com/gitlab-org/gitlab-foss/-/tree/master/lib/gitlab/ci/templates
|
||||
Reference in New Issue
Block a user