다른 파일의 CI/CD 설정 사용하기

다른 파일의 CI/CD 설정 사용하기

include로 외부 YAML 파일을 CI/CD 작업에 포함하는 방법을 설명하는 문서예요. 설정 파일을 여러 곳에서 재사용해 중복을 줄이고 유지보수를 쉽게 만드는 것이 핵심이에요.

단일·배열 포함, default 사용, 설정 값 재정의(오버라이드), 병합 규칙, 중첩 include, rules와의 조합까지 폭넓게 옆에서 설명해 주는 방식으로 정리했어요.

출처: 문서

본문

include를 사용해 외부 YAML 파일을 CI/CD 작업에 포함할 수 있어요.

단일 설정 파일 포함하기

단일 설정 파일을 포함하려면 include에 단일 파일을 다음 두 문법 중 하나로 사용하세요.

  • 같은 줄에:
    include: 'my-config.yml'
    
  • 배열의 단일 항목으로:
    include:
      - 'my-config.yml'
    

파일이 로컬 파일이면 include:local과 동일하게 동작해요. 파일이 원격 파일이면 include:remote와 동일해요.

설정 파일 배열 포함하기

설정 파일의 배열을 포함할 수 있어요.

  • include 유형을 지정하지 않으면 각 배열 항목은 필요에 따라 기본적으로 include:local 또는 include:remote로 설정돼요.
    include:
      - 'https://gitlab.com/awesome-project/raw/main/.before-script-template.yml'
      - 'templates/.after-script-template.yml'
    
  • 단일 항목 배열을 정의할 수 있어요.
    include:
      - remote: 'https://gitlab.com/awesome-project/raw/main/.before-script-template.yml'
    
  • 여러 include 유형을 명시적으로 지정한 배열을 정의할 수 있어요.
    include:
      - remote: 'https://gitlab.com/awesome-project/raw/main/.before-script-template.yml'
      - local: 'templates/.after-script-template.yml'
      - template: Auto-DevOps.gitlab-ci.yml
    
  • 기본 유형과 특정 include 유형을 결합한 배열을 정의할 수 있어요.
    include:
      - 'https://gitlab.com/awesome-project/raw/main/.before-script-template.yml'
      - 'templates/.after-script-template.yml'
      - template: Auto-DevOps.gitlab-ci.yml
      - project: 'my-group/my-project'
        ref: main
        file: 'templates/.gitlab-ci-template.yml'
    

포함된 설정 파일의 default 구성 사용하기

설정 파일에 default 섹션을 정의할 수 있어요. include 키워드와 함께 default 섹션을 사용하면 기본값이 파이프라인의 모든 작업에 적용돼요.

예를 들어 before_script와 함께 default 섹션을 사용할 수 있어요.

/templates/.before-script-template.yml이라는 사용자 정의 설정 파일의 내용:

default:
  before_script:
    - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
    - gem install bundler --no-document
    - bundle install --jobs $(nproc)  "${FLAGS[@]}"

.gitlab-ci.yml의 내용:

include: 'templates/.before-script-template.yml'

rspec1:
  script:
    - bundle exec rspec

rspec2:
  script:
    - bundle exec rspec

기본 before_script 명령은 두 rspec 작업 모두에서 script 명령보다 먼저 실행돼요.

포함된 설정 값 재정의하기

include 키워드를 사용할 때 포함된 설정 값을 재정의해 파이프라인 요구 사항에 맞게 조정할 수 있어요.

다음 예시는 .gitlab-ci.yml 파일에서 사용자 정의된 include 파일을 보여줘요. 특정 YAML 정의 변수와 production 작업의 세부 사항이 재정의돼요.

autodevops-template.yml이라는 사용자 정의 설정 파일의 내용:

variables:
  POSTGRES_USER: user
  POSTGRES_PASSWORD: testing_password
  POSTGRES_DB: $CI_ENVIRONMENT_SLUG

production:
  stage: production
  script:
    - install_dependencies
    - deploy
  environment:
    name: production
    url: https://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

.gitlab-ci.yml의 내용:

include: 'https://company.com/autodevops-template.yml'

default:
  image: alpine:latest

variables:
  POSTGRES_USER: root
  POSTGRES_PASSWORD: secure_password

stages:
  - build
  - test
  - production

production:
  environment:
    url: https://domain.com

.gitlab-ci.yml 파일에 정의된 POSTGRES_USERPOSTGRES_PASSWORD 변수와 production 작업의 environment:urlautodevops-template.yml 파일에 정의된 값을 재정의해요. 다른 키워드는 변경되지 않아요. 이 방법을 *병합(merging)*이라고 해요.

include의 병합 방법

include 구성은 다음 과정으로 메인 설정 파일과 병합돼요.

  • 포함된 파일은 설정 파일에 정의된 순서대로 읽히고, 포함된 구성도 같은 순서로 병합돼요.
  • 포함된 파일이 include를 사용하면 그 중첩 include 구성이 먼저 (재귀적으로) 병합돼요.
  • 매개변수가 겹치면 포함된 파일의 구성을 병합할 때 마지막으로 포함된 파일이 우선해요.
  • include로 추가된 모든 구성이 병합된 후, 메인 구성이 포함된 구성과 병합돼요.

이 병합 방법은 *딥 병합(deep merge)*으로, 해시 맵이 구성의 어느 깊이에서든 병합돼요. 지금까지 병합된 구성을 포함하는 해시 맵 "A"와 (다음 구성 조각) "B"를 병합할 때 키와 값은 다음과 같이 처리돼요.

  • 키가 A에만 있으면 A의 키와 값을 사용.
  • 키가 A와 B 모두에 있고 둘 다 해시 맵이면 그 해시 맵들을 병합.
  • 키가 A와 B 모두에 있고 한쪽 값이 해시 맵이 아니면 B의 값을 사용.
  • 그 외에는 B의 키와 값을 사용.

예를 들어 두 파일로 구성된 설정을 볼게요.

.gitlab-ci.yml 파일:

include: 'common.yml'

variables:
  POSTGRES_USER: username

test:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      when: manual
  artifacts:
    reports:
      junit: rspec.xml

common.yml 파일:

variables:
  POSTGRES_USER: common_username
  POSTGRES_PASSWORD: testing_password

test:
  rules:
    - when: never
  script:
    - echo LOGIN=${POSTGRES_USER} > deploy.env
    - rake spec
  artifacts:
    reports:
      dotenv: deploy.env

병합 결과:

variables:
  POSTGRES_USER: username
  POSTGRES_PASSWORD: testing_password

test:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      when: manual
  script:
    - echo LOGIN=${POSTGRES_USER} > deploy.env
    - rake spec
  artifacts:
    reports:
      junit: rspec.xml
      dotenv: deploy.env

이 예시에서:

  • 변수는 모든 파일이 병합된 후에만 평가돼요. 포함된 파일의 작업이 다른 파일에 정의된 변수 값을 사용할 수도 있어요. 병합 후 CI/CD 변수 우선순위가 각 변수의 최종 값을 결정해요.
  • rules는 배열이라 병합할 수 없어요. 최상위 파일이 우선해요.
  • artifacts는 해시 맵이라 딥 병합될 수 있어요.

포함된 구성 배열 재정의하기

병합을 사용해 포함된 템플릿의 구성을 확장하고 재정의할 수 있지만, 배열의 개별 항목을 추가하거나 수정할 수는 없어요. 예를 들어 확장된 production 작업의 script 배열에 추가 notify_owner 명령을 추가하려면:

autodevops-template.yml의 내용:

production:
  stage: production
  script:
    - install_dependencies
    - deploy

.gitlab-ci.yml의 내용:

include: 'autodevops-template.yml'

stages:
  - production

production:
  script:
    - install_dependencies
    - deploy
    - notify_owner

.gitlab-ci.yml 파일에서 install_dependenciesdeploy를 반복하지 않으면 production 작업의 스크립트에는 notify_owner만 있게 돼요.

중첩 include 사용하기

다른 구성에 포함되는 구성 파일에서 include 섹션을 중첩할 수 있어요. 예를 들어 세 단계 깊이로 중첩된 include 키워드는 다음과 같아요.

.gitlab-ci.yml의 내용:

include:
  - local: /.gitlab-ci/another-config.yml

/.gitlab-ci/another-config.yml의 내용:

include:
  - local: /.gitlab-ci/config-defaults.yml

/.gitlab-ci/config-defaults.yml의 내용:

default:
  after_script:
    - echo "Job complete."

중복 include 항목으로 중첩 include 사용하기

메인 설정 파일과 중첩 include에서 같은 설정 파일을 여러 번 포함할 수 있어요.

어떤 파일이 재정의(overrides)로 포함된 구성을 변경한다면 include 항목의 순서가 최종 구성에 영향을 줄 수 있어요. 구성이 마지막으로 포함된 시점이 이전에 포함된 시점을 재정의해요. 예를 들어:

defaults.gitlab-ci.yml 파일의 내용:

default:
  before_script: echo "Default before script"

unit-tests.gitlab-ci.yml 파일의 내용:

include:
  - template: defaults.gitlab-ci.yml

default:  # Override the included default
  before_script: echo "Unit test default override"

unit-test-job:
  script: unit-test.sh

smoke-tests.gitlab-ci.yml 파일의 내용:

include:
  - template: defaults.gitlab-ci.yml

default:  # Override the included default
  before_script: echo "Smoke test default override"

smoke-test-job:
  script: smoke-test.sh

이 세 파일로, 포함되는 순서가 최종 구성을 바꿔요.

unit-tests가 먼저 포함된 경우 .gitlab-ci.yml 파일의 내용:

include:
  - local: unit-tests.gitlab-ci.yml
  - local: smoke-tests.gitlab-ci.yml

최종 구성은 다음과 같아요.

unit-test-job:
 before_script: echo "Smoke test default override"
 script: unit-test.sh

smoke-test-job:
 before_script: echo "Smoke test default override"
 script: smoke-test.sh

unit-tests가 마지막에 포함된 경우 .gitlab-ci.yml 파일의 내용:

include:
  - local: smoke-tests.gitlab-ci.yml
  - local: unit-tests.gitlab-ci.yml

최종 구성은 다음과 같아요.

unit-test-job:
 before_script: echo "Unit test default override"
 script: unit-test.sh

smoke-test-job:
 before_script: echo "Unit test default override"
 script: smoke-test.sh

어떤 파일도 포함된 구성을 재정의하지 않으면 include 항목의 순서는 최종 구성에 영향을 주지 않아요.

include와 함께 변수 사용하기

.gitlab-ci.yml 파일의 include 섹션에서 다음을 사용할 수 있어요.

예를 들어:

include:
  project: '$CI_PROJECT_PATH'
  file: '.compliance-gitlab-ci.yml'

작업에서 정의된 변수나 모든 작업의 기본 변수를 정의하는 전역 variables 섹션의 변수는 사용할 수 없어요. Include는 작업보다 먼저 평가되므로 이 변수들은 include와 함께 사용할 수 없어요.

사전 정의 변수를 포함하는 방법과 변수가 CI/CD 작업에 미치는 영향의 예시는 이 CI/CD 변수 데모를 참고하세요.

동적 하위 파이프라인의 구성에는 include 섹션에서 CI/CD 변수를 사용할 수 없어요. 이 문제는 이슈 378717에서 수정을 제안하고 있어요.

include와 함께 rules 사용하기

rulesinclude와 함께 사용해 다른 설정 파일을 조건부로 포함할 수 있어요.

rules특정 변수와 다음 키워드에서만 사용할 수 있어요.

rules:if와 함께 include 사용

rules:if를 사용해 CI/CD 변수의 상태에 따라 다른 설정 파일을 조건부로 포함하세요. 예를 들어:

include:
  - local: builds.yml
    rules:
      - if: $DONT_INCLUDE_BUILDS == "true"
        when: never
  - local: builds.yml
    rules:
      - if: $ALWAYS_INCLUDE_BUILDS == "true"
        when: always
  - local: builds.yml
    rules:
      - if: $INCLUDE_BUILDS == "true"
  - local: deploys.yml
    rules:
      - if: $CI_COMMIT_BRANCH == "main"

test:
  stage: test
  script: exit 0

rules:exists와 함께 include 사용

이력

  • regexp: 지원은 GitLab 19.2에서 도입.

rules:exists를 사용해 파일 존재 여부에 따라 다른 설정 파일을 조건부로 포함하세요. 예를 들어:

include:
  - local: builds.yml
    rules:
      - exists:
          - exception-file.md
        when: never
  - local: builds.yml
    rules:
      - exists:
          - important-file.md
        when: always
  - local: builds.yml
    rules:
      - exists:
          - file.md

test:
  stage: test
  script: exit 0

이 예시에서 GitLab은 현재 프로젝트에서 file.md의 존재를 확인해요.

다른 프로젝트의 include 파일에서 rules:exists와 함께 include를 사용한다면 구성을 주의 깊게 검토하세요. GitLab은 파일 존재를 다른 프로젝트에서 확인해요. 예를 들어:

# Pipeline configuration in my-group/my-project
include:
  - project: my-group/other-project
    ref: other_branch
    file: other-file.yml

test:
  script: exit 0

# other-file.yml in my-group/other-project on ref other_branch
include:
  - project: my-group/my-project
    ref: main
    file: my-file.yml
    rules:
      - exists:
          - file.md

이 예시에서 GitLab은 file.md의 존재를 파이프라인이 실행되는 프로젝트/ref가 아니라 my-group/other-project의 커밋 ref other_branch에서 검색해요.

검색 컨텍스트를 변경하려면 rules:exists:paths와 함께 rules:exists:project를 사용할 수 있어요. 예를 들어:

include:
  - project: my-group/my-project
    ref: main
    file: my-file.yml
    rules:
      - exists:
          paths:
            - file.md
          project: my-group/my-project
          ref: main

rules:changes와 함께 include 사용

이력

  • regexp: 지원은 GitLab 19.2에서 도입.

rules:changes를 사용해 변경된 파일에 따라 다른 설정 파일을 조건부로 포함하세요. 예를 들어:

include:
  - local: builds1.yml
    rules:
      - changes:
        - Dockerfile
  - local: builds2.yml
    rules:
      - changes:
          paths:
            - Dockerfile
          compare_to: 'refs/heads/branch1'
        when: always
  - local: builds3.yml
    rules:
      - if: $CI_PIPELINE_SOURCE == "merge_request_event"
        changes:
          paths:
            - Dockerfile

test:
  stage: test
  script: exit 0

이 예시에서:

  • Dockerfile이 변경되면 builds1.yml이 포함돼요.
  • Dockerfilerefs/heads/branch1에 상대적으로 변경되면 builds2.yml이 포함돼요.
  • Dockerfile이 변경되고 파이프라인 소스가 머지 리퀘스트 이벤트이면 builds3.yml이 포함돼요. builds3.yml의 작업들도 머지 리퀘스트 파이프라인에서 실행되도록 구성해야 해요.

와일드카드 파일 경로와 함께 include:local 사용하기

include:local에서 와일드카드 경로(***)를 사용할 수 있어요.

예시:

include: 'configs/*.yml'

파이프라인이 실행될 때 GitLab은:

  • configs 디렉터리의 모든 .yml 파일을 파이프라인 구성에 추가해요.
  • configs 디렉터리의 하위 폴더에 있는 .yml 파일은 추가하지 않아요. 이를 허용하려면 다음 구성을 추가하세요.
    # This matches all `.yml` files in `configs` and any subfolder in it.
    include: 'configs/**.yml'
    
    # This matches all `.yml` files only in subfolders of `configs`.
    include: 'configs/**/*.yml'
    

문제 해결

Maximum of 150 nested includes are allowed! 오류

파이프라인의 중첩 포함 파일 최대 개수는 150개예요. 파이프라인에서 Maximum 150 includes are allowed 오류 메시지를 받으면 다음 중 하나일 가능성이 높아요.

  • 포함된 중첩 구성 중 일부가 비정상적으로 많은 수의 추가 중첩 include 구성을 포함함.
  • 중첩 include에 우발적 순환이 있음. 예를 들어 include1.ymlinclude2.yml을 포함하고 include2.ymlinclude1.yml을 포함해 재귀 루프를 만드는 경우.

이런 위험을 줄이려면 제한에 도달했는지 검증하는 파이프라인 편집기로 파이프라인 설정 파일을 편집하세요. 한 번에 하나씩 포함 파일을 제거해 순환이나 과도한 포함 파일의 원인이 되는 설정 파일을 좁혀 나갈 수 있어요.

GitLab Self-Managed 사용자는 최대 include 수 값을 변경할 수 있어요.

오류: include:local에서 Local file <file> does not exist!

include:local을 사용할 때 파일이 저장소에 존재함에도 Local file <file> does not exist! 오류를 받을 수 있어요.

이 오류는 CI/CD 구성 문제가 아닌 알려진 시스템 수준 이슈예요. 분산 Gitaly 또는 Praefect 설정에서 간헐적으로 관찰돼요. 이 오류가 발생하면 파이프라인을 다시 시도하세요.

자세한 내용은 이슈 336789을 참고하세요.

SSL_connect SYSCALL returned=5 errno=0 state=SSLv3/TLS write client hello 및 기타 네트워크 오류

include:remote를 사용할 때 GitLab은 HTTP(S)를 통해 원격 파일을 가져오려고 해요. 이 과정은 다양한 연결 문제로 실패할 수 있어요.

SSL_connect SYSCALL returned=5 errno=0 state=SSLv3/TLS write client hello 오류는 GitLab이 원격 호스트에 HTTPS 연결을 설정할 수 없을 때 발생해요. 원격 호스트가 요청으로 서버에 과부하가 걸리는 것을 방지하는 속도 제한(rate limit)이 있는 경우 이 문제가 발생할 수 있어요.

예를 들어 GitLab.com의 GitLab Pages 서버는 속도 제한이 있어요. GitLab Pages에 호스팅된 CI/CD 구성 파일을 반복적으로 가져오려 하면 속도 제한에 도달해 오류가 발생할 수 있어요. CI/CD 구성 파일을 GitLab Pages 사이트에 호스팅하는 것은 피해야 해요.

가능하면 include:project를 사용해 외부 HTTP(S) 요청 없이 GitLab 인스턴스의 다른 프로젝트에서 구성 파일을 가져오세요.

더 알아보기

include가 제공하는 각 유형(local, remote, template, project)의 세부 문법은 CI/CD YAML 문법 참조에서 확인할 수 있어요. default·rules 키워드와 함께 조합해 구성의 재사용성을 높이는 방법도 함께 익히면 좋아요.