Skip to content
Back to skills

1644 Pipeline Optimization 6fdc5e1b

ASecurity

Best practices for optimizing GitLab CI/CD pipeline performance, reducing build times, and efficient resource usage.

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 11, 2026
devopspythonnodedockergitapidatabasefrontendbackendci/cdperformance

Works with

  • cli
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 1644-pipeline-optimization_6fdc5e1b --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 1644 Pipeline Optimization 6fdc5e1b?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 1644 Pipeline Optimization 6fdc5e1b
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-1644-pipeline-optimization-6fdc5e1b/badge)](https://www.skillsdirectory.com/skills/tools-only-1644-pipeline-optimization-6fdc5e1b)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# GitLab CI/CD Pipeline Optimization Guide

Best practices for optimizing GitLab CI/CD pipeline performance, reducing build times, and efficient resource usage.

## Overview

Efficient CI/CD pipelines are critical for developer productivity and cost management. This guide covers caching strategies, job parallelization, Docker optimization, and resource management.

## Caching Strategies

Caching reduces redundant work by preserving dependencies and build artifacts between pipeline runs.

### Basic Cache Configuration

```yaml
variables:
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - .cache/pip
    - venv/
```

### Cache Key Strategies

**Per-branch caching** (isolates changes):

```yaml
cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - node_modules/
```

**Shared cache** (faster but may have stale data):

```yaml
cache:
  key: shared-cache
  paths:
    - node_modules/
```

**Dependency-based cache** (invalidates when dependencies change):

```yaml
cache:
  key:
    files:
      - package-lock.json
  paths:
    - node_modules/
```

### Pull-Push Policy

Optimize cache usage with pull-push policies:

```yaml
# Default: pull-push (download and upload)
cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - node_modules/
  policy: pull-push

# Build job: pull-push (downloads and uploads)
build:
  cache:
    policy: pull-push

# Test job: pull (only downloads, faster)
test:
  cache:
    policy: pull
```

### Python Caching Example

```yaml
variables:
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
  UV_CACHE_DIR: "$CI_PROJECT_DIR/.cache/uv"

cache:
  key:
    files:
      - pyproject.toml
      - uv.lock
  paths:
    - .cache/pip
    - .cache/uv
    - .venv/

install:
  script:
    - uv venv
    - uv sync --frozen
  cache:
    policy: pull-push

test:
  script:
    - uv run pytest
  cache:
    policy: pull
```

### Node.js Caching Example

```yaml
cache:
  key:
    files:
      - package-lock.json
  paths:
    - node_modules/
    - .npm/

install:
  script:
    - npm ci --cache .npm --prefer-offline
  cache:
    policy: pull-push

test:
  script:
    - npm test
  cache:
    policy: pull
```

## Job Parallelization

Run independent jobs concurrently to reduce total pipeline time.

### Parallel Keyword

Run the same job multiple times in parallel:

```yaml
test:
  parallel: 5
  script:
    - npm test -- --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
```

### Matrix Builds

Test against multiple versions or configurations:

```yaml
test:
  parallel:
    matrix:
      - PYTHON_VERSION: ["3.11", "3.12", "3.13"]
  image: python:${PYTHON_VERSION}
  script:
    - uv run pytest
```

### Stage Parallelization

Run independent jobs in the same stage:

```yaml
stages:
  - test

lint:ruff:
  stage: test
  script:
    - uv run ruff check

lint:mypy:
  stage: test
  script:
    - uv run mypy .

test:unit:
  stage: test
  script:
    - uv run pytest tests/unit

test:integration:
  stage: test
  script:
    - uv run pytest tests/integration
```

All four jobs run concurrently in the `test` stage.

## Docker Optimization

### Use Specific Image Tags

Avoid `latest` tags for reproducibility:

```yaml
# ❌ Avoid
image: python:latest

# ✅ Use specific version
image: python:3.12-slim
```

### Smaller Base Images

Use slim or alpine variants:

```yaml
# Standard image: ~900MB
image: python:3.12

# Slim image: ~120MB
image: python:3.12-slim

# Alpine image: ~50MB (may have compatibility issues)
image: python:3.12-alpine
```

### Multi-Stage Dockerfile

Build smaller production images:

```dockerfile
# Build stage
FROM python:3.12 AS builder
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN pip install uv && uv venv && uv sync --frozen

# Production stage
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /app/.venv .venv
COPY . .
CMD [".venv/bin/python", "app.py"]
```

### Docker Layer Caching

Enable Docker layer caching in GitLab:

```yaml
build:
  image: docker:latest
  services:
    - docker:dind
  variables:
    DOCKER_DRIVER: overlay2
    DOCKER_BUILDKIT: 1
  script:
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
  cache:
    key: docker-layers
    paths:
      - .docker-cache/
```

### Docker-in-Docker Optimization

```yaml
variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"

build:
  image: docker:latest
  services:
    - docker:dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
```

## Job Dependencies and Needs

Control job execution order and parallelization:

### Default: Sequential Stages

```yaml
stages:
  - build
  - test
  - deploy

build:
  stage: build
  script:
    - npm run build

test:
  stage: test
  script:
    - npm test

deploy:
  stage: deploy
  script:
    - npm run deploy
```

All `build` jobs complete before any `test` jobs start.

### Needs: Directed Acyclic Graph (DAG)

Run jobs as soon as dependencies complete:

```yaml
stages:
  - build
  - test
  - deploy

build:backend:
  stage: build
  script:
    - npm run build:backend

build:frontend:
  stage: build
  script:
    - npm run build:frontend

test:backend:
  stage: test
  needs: [build:backend]
  script:
    - npm test:backend

test:frontend:
  stage: test
  needs: [build:frontend]
  script:
    - npm test:frontend

deploy:
  stage: deploy
  needs: [test:backend, test:frontend]
  script:
    - npm run deploy
```

`test:backend` starts as soon as `build:backend` completes, without waiting for `build:frontend`.

## Artifact Management

### Selective Artifact Paths

Only preserve necessary files:

```yaml
build:
  script:
    - npm run build
  artifacts:
    paths:
      - dist/
      - build/
    exclude:
      - dist/**/*.map
      - build/**/*.log
```

### Artifact Expiration

Set appropriate expiration to save storage:

```yaml
test:
  script:
    - npm test
  artifacts:
    paths:
      - coverage/
    expire_in: 7 days
```

### Artifact Dependencies

Only download required artifacts:

```yaml
build:
  script:
    - npm run build
  artifacts:
    paths:
      - dist/

deploy:
  dependencies:
    - build
  script:
    - npm run deploy
```

`deploy` only downloads artifacts from `build`, not other jobs.

## Conditional Job Execution

Run jobs only when necessary:

### Rules

```yaml
test:
  script:
    - npm test
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

deploy:
  script:
    - npm run deploy
  rules:
    - if: $CI_COMMIT_TAG
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      when: manual
```

### Only/Except (Legacy)

```yaml
test:
  script:
    - npm test
  only:
    - merge_requests
    - main

deploy:
  script:
    - npm run deploy
  only:
    - tags
    - main
  except:
    - schedules
```

### Changes

Run jobs only when specific files change:

```yaml
build:frontend:
  script:
    - npm run build:frontend
  rules:
    - changes:
        - frontend/**/*
        - package.json

build:backend:
  script:
    - npm run build:backend
  rules:
    - changes:
        - backend/**/*
        - pyproject.toml
```

## Resource Management

### Job Timeout

Prevent hanging jobs:

```yaml
test:
  script:
    - npm test
  timeout: 1h
```

### Retry Failed Jobs

```yaml
test:
  script:
    - npm test
  retry:
    max: 2
    when:
      - runner_system_failure
      - stuck_or_timeout_failure
```

### Runner Tags

Use specific runners for resource-intensive jobs:

```yaml
build:
  tags:
    - docker
    - high-cpu
  script:
    - npm run build

test:
  tags:
    - docker
  script:
    - npm test
```

## Environment Variables

### Project Variables

Store configuration in GitLab CI/CD settings (Settings → CI/CD → Variables):

- `DATABASE_URL`
- `API_KEY`
- `DEPLOYMENT_TOKEN`

Mark sensitive variables as **Masked** and **Protected**.

### Variable Precedence

1. Trigger variables (highest priority)
2. Project-level variables
3. Group-level variables
4. Instance-level variables
5. Variables defined in `.gitlab-ci.yml`
6. Predefined variables (lowest priority)

### Masked Variables

Prevent secrets from appearing in logs:

```yaml
variables:
  DATABASE_URL: $DATABASE_URL # Masked in GitLab settings

deploy:
  script:
    - echo "Deploying to $DATABASE_URL" # Will show [MASKED]
```

## Pipeline Efficiency Metrics

Monitor and optimize based on metrics:

### Key Metrics

- **Pipeline duration**: Total time from start to finish
- **Job duration**: Time for individual jobs
- **Queue time**: Time waiting for available runners
- **Cache hit rate**: Percentage of cache hits vs misses
- **Artifact size**: Size of stored artifacts

### Monitoring

```yaml
test:
  script:
    - start_time=$(date +%s)
    - npm test
    - end_time=$(date +%s)
    - echo "Test duration: $((end_time - start_time)) seconds"
```

## Complete Example: Optimized Pipeline

```yaml
variables:
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
  UV_CACHE_DIR: "$CI_PROJECT_DIR/.cache/uv"

stages:
  - lint
  - test
  - build
  - deploy

cache:
  key:
    files:
      - pyproject.toml
      - uv.lock
  paths:
    - .cache/pip
    - .cache/uv
    - .venv/

.python_base:
  image: python:3.12-slim
  before_script:
    - pip install uv
    - uv venv
    - uv sync --frozen

lint:ruff:
  extends: .python_base
  stage: lint
  script:
    - uv run ruff check
  cache:
    policy: pull

lint:mypy:
  extends: .python_base
  stage: lint
  script:
    - uv run mypy .
  cache:
    policy: pull

test:
  extends: .python_base
  stage: test
  parallel:
    matrix:
      - PYTHON_VERSION: ["3.11", "3.12"]
  image: python:${PYTHON_VERSION}-slim
  script:
    - uv run pytest --cov
  artifacts:
    paths:
      - htmlcov/
    expire_in: 7 days
  cache:
    policy: pull

build:
  extends: .python_base
  stage: build
  needs: [test]
  script:
    - uv build
  artifacts:
    paths:
      - dist/
    expire_in: 30 days
  rules:
    - if: $CI_COMMIT_TAG
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

deploy:
  stage: deploy
  needs: [build]
  dependencies:
    - build
  script:
    - uv publish --token $PYPI_TOKEN
  rules:
    - if: $CI_COMMIT_TAG
  environment:
    name: production
```

## Best Practices Summary

1. **Use caching effectively** - Cache dependencies with appropriate keys
2. **Parallelize jobs** - Run independent jobs concurrently
3. **Optimize Docker images** - Use slim base images and layer caching
4. **Use job dependencies** - Use `needs` for DAG execution
5. **Manage artifacts** - Set expiration and selective paths
6. **Conditional execution** - Use `rules` to run only necessary jobs
7. **Set timeouts** - Prevent hanging jobs
8. **Monitor metrics** - Track duration, cache hits, artifact size
9. **Use runner tags** - Direct jobs to appropriate runners
10. **Secure variables** - Mask sensitive data and use protected variables

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.