Как определить опции запуска пайплайна при редактировании определенных ресурсов в Git?

«Как определить опции запуска пайплайна при редактировании определенных ресурсов в Git?» — вопрос из категории CI/CD, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В CI/CD пайплайнах я настраиваю условное выполнение на основе измененных файлов, чтобы оптимизировать время сборки и запускать только релевантные этапы. Вот как я это реализовывал в разных системах:

В GitLab CI/CD: Использую правило changes в секции rules задания (job).

build_backend:
  script:
    - ./build-backend.sh
  rules:
    - changes:
        - backend/**/*
        - go.mod
        - go.sum
      when: on_success
    - when: never  # Не запускать, если изменения не в backend

deploy_infrastructure:
  script:
    - terraform apply -auto-approve
  rules:
    - changes:
        - terraform/**/*
      when: on_success
    - when: never

В GitHub Actions: Использую действие dorny/paths-filter для создания выходных переменных, которые затем используются в условиях if.

jobs:
  changes:
    runs-on: ubuntu-latest
    outputs:
      backend: ${{ steps.filter.outputs.backend }}
      frontend: ${{ steps.filter.outputs.frontend }}
    steps:
      - uses: dorny/paths-filter@v2
        id: filter
        with:
          filters: |
            backend:
              - 'src/backend/**'
              - 'package-lock.json'
            frontend:
              - 'src/frontend/**'
              - 'package.json'

  build_backend:
    runs-on: ubuntu-latest
    needs: changes
    if: ${{ needs.changes.outputs.backend == 'true' }}
    steps:
      - run: echo "Building backend..."

  build_frontend:
    runs-on: ubuntu-latest
    needs: changes
    if: ${{ needs.changes.outputs.frontend == 'true' }}
    steps:
      - run: echo "Building frontend..."

В Jenkins с использованием Jenkinsfile (Declarative Pipeline): Использую директиву when с условием changeset.

pipeline {
    agent any
    stages {
        stage('Build Docker Image') {
            when {
                changeset 'Dockerfile,**/package*.json'
            }
            steps {
                sh 'docker build -t myapp .'
            }
        }
        stage('Terraform Plan') {
            when {
                changeset 'terraform/**'
            }
            steps {
                dir('terraform') {
                    sh 'terraform plan'
                }
            }
        }
    }
}

Общий подход с помощью скрипта: Иногда, для более сложной логики, я пишу скрипт, который анализирует git diff.

#!/bin/bash
# В шаге пайплайна
CHANGED_FILES=$(git diff --name-only HEAD~1)

if echo "$CHANGED_FILES" | grep -q "^infrastructure/kubernetes/.*.yaml$"; then
    echo "K8s manifests changed. Running helm upgrade..."
    helm upgrade myapp ./charts/myapp
fi

if echo "$CHANGED_FILES" | grep -q "^src/.*.go$"; then
    echo "Go source changed. Running tests..."
    go test ./...
fi

Такой подход позволяет избежать ненужных запусков полного пайплайна и значительно ускоряет процесс CI/CD.