GitLab CI/CD 템플릿 개발 가이드

note
CI/CD 카탈로그가 소개되면서, GitLab은 더 이상 코드베이스에 새로운 CI/CD 템플릿을 받아들이지 않습니다. 대신에, 팀 멤버들에게 CI/CD 구성요소를 카탈로그에 추가하도록 권장합니다. 이전과 달리, 이러한 전환이 공유 CI/CD 리소스의 모듈성과 유지보수성을 향상시키고, 새로운 CI/CD 템플릿을 기여하는 복잡성을 피합니다. 기존 템플릿을 업데이트해야 하는 경우 해당 CI/CD 구성요소도 업데이트해야 합니다. 아직 해당 CI/CD 템플릿과 일치하는 구성요소가 없는 경우, 일치하는 구성요소를 생성할 것을 고려해야 합니다. 이렇게 하면 템플릿과 구성요소 기능이 계속 동기화되어 새로운 개발 관행과 일치하게 됩니다.

이 문서는 GitLab CI/CD 템플릿의 개발 방법에 대해 설명합니다.

CI/CD 템플릿 요구 사항

새로운 또는 업데이트된 CI/CD 템플릿으로 Merge Request을 제출하기 전에 다음을 해야 합니다:

  • 템플릿을 올바른 디렉터리에 배치합니다.
  • CI/CD 템플릿 작성 지침을 준수합니다.
  • *.gitlab-ci.yml 형식에 따라 템플릿의 이름을 정합니다.
  • 유효한 .gitlab-ci.yml 구문을 사용합니다. CI/CD 린트 도구로 유효성을 검사합니다.
  • 템플릿 메트릭을 추가합니다.
  • Merge Request이 사용자에게 노출되는 변경을 도입하는 경우 변경 로그를 포함합니다.
  • 템플릿 검토 프로세스를 따릅니다.
  • (선택적이지만 강력히 권장함) 리뷰어가 접근할 수 있는 예제 GitLab 프로젝트에서 템플릿을 테스트합니다. 리뷰어는 템플릿이 올바른지 확인하기 위해 종종 데이터나 구성을 생성할 수 없을 수 있기 때문에, 예제 프로젝트 파이프라인이 제출 전에 성공해야 합니다.

템플릿 디렉터리

모든 템플릿 파일은 lib/gitlab/ci/templates에 저장됩니다. 일반적인 템플릿을 이 디렉터리에 저장하지만, 특정 템플릿 유형에는 해당하는 디렉터리가 별도로 예약되어 있습니다. 새 파일 UI에서 템플릿을 선택할 수 있는지 확인 하려면 해당 디렉터리에 파일이 위치해야 합니다:

하위 디렉터리 UI에서 선택 가능 템플릿 유형
/* (루트) 일반 템플릿
/AWS/* 아니요 클라우드 배포(AWS)와 관련된 템플릿
/Jobs/* 아니요 Auto DevOps와 관련된 템플릿
/Pages/* GitLab Pages로 정적 사이트 생성기를 사용하는 샘플 템플릿
/Security/* 보안 스캐너와 관련된 템플릿
/Terraform/* 아니요 인프라스트럭처 코드(Terraform)와 관련된 템플릿
/Verify/* 테스트 기능과 관련된 템플릿
/Workflows/* 아니요 workflow: 키워드를 사용하는 샘플 템플릿

템플릿 작성 지침

템플릿 제출이 표준을 따르도록 하려면 다음 지침을 사용합니다:

템플릿 유형

템플릿에는 프로젝트 구조, 언어 등과 일치하는 종단 간 CI/CD 워크플로우를 제공하는 두 가지 다른 유형이 있으며, 템플릿의 스타일은 이 두 유형 중 하나와 일치해야 합니다:

파이프라인 템플릿은 프로젝트에 더 이상 .gitlab-ci.yml 파일이 없는 프로젝트에서 스스로 사용해야 합니다.

파이프라인 템플릿을 작성할 때:

  • imagebefore_script와 같은 전역 키워드를 템플릿 상단의 default 섹션에 배치합니다.
  • 템플릿이 기존의 .gitlab-ci.yml 파일의 includes 키워드와 함께 사용되는지, 혹은 같이 사용된다면 코드 주석으로 명확히 설명합니다.

작업 템플릿은 특정 작업을 수행하기 위해 기존의 CI/CD 워크플로에 추가할 수 있는 특정 작업을 제공합니다.

작업 템플릿을 작성할 때:

  • 전역이나 default 키워드를 사용하지 않습니다. 루트 .gitlab-ci.yml이 템플릿을 포함하는 경우, 전역이나 기본 키워드가 무시될 수 있고 예상치 못한 동작을 일으킬 수 있습니다. 작업 템플릿이 특정 스테이지를 필요로 하는 경우, 코드 주석에서 사용자가 주요 .gitlab-ci.yml 구성에 해당 스테이지를 매뉴얼으로 추가해야 한다고 설명합니다.
  • 템플릿이 includes 키워드와 함께 사용되거나 기존 구성에 복사되도록 설계되었는지 코드 주석에서 명확히 설명합니다.
  • 버전을 고려해 템플릿을 최신 및 안정 버전으로 관리하여 역호환성 문제를 피합니다. includes로 가져오는 템플릿의 유지보수는 더 복잡하며, 템플릿 변경 사항이 모든 템플릿을 사용하고 있는 모든 프로젝트의 파이프라인을 망가뜨릴 수 있습니다.

템플릿을 작성할 때 추가로 고려해야 할 사항:

템플릿 설계 지점 파이프라인 템플릿 작업 템플릿
stages를 포함하여 전역 키워드를 사용할 수 있습니다. 아니요
작업을 정의할 수 있습니다.
새 파일 UI에서 선택 가능합니다. 아니요
include를 사용하여 다른 작업 템플릿을 포함할 수 있습니다. 아니요
include를 사용하여 다른 파이프라인 템플릿을 포함할 수 있습니다. 아니요 아니요

구문 지침

템플릿을 이해하기 쉽게 만들기 위해, 일관된 형식으로 명확한 구문 스타일을 사용해야 합니다.

각 작업의 before_script, script, after_script 키워드는 ShellCheck를 사용하여 린트되며 Shell 스크립팅 표준 및 스타일 지침을 가능한 한 준수해야 합니다.

ShellCheck는 해당 스크립트가 Bash에서 실행되도록 설계되었다고 가정합니다. Bash ShellCheck 규칙과 호환되지 않는 셸을 사용하는 템플릿은 ShellCheck 린트에서 제외될 수 있습니다. 스크립트를 제외하려면 scripts/lint_templates_bash.rbEXCLUDED_TEMPLATES 디렉터리에 추가하십시오.

기본 브랜치 하드코딩 금지

$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH를 사용하여 하드코딩된 main 브랜치 대신에 사용합니다. 절대 master를 사용하지 마세요:

job1:
  rules:
    if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  script:
    echo "example job 1"

job2:
  only:
    variables:
      - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  script:
    echo "example job 2"

onlyexcept 대신 rules 사용

가능한 경우 onlyexcept를 사용하지 말고 rules를 사용하세요. onlyexcept는 더 이상 개발되지 않으며 rules가 이제는 우선되는 구문입니다:

job2:
  script:
    - echo
  rules:
    - if: $CI_COMMIT_BRANCH

명령어를 길게 분할

명령어가 너무 길거나 -o--option과 같은 명령행 플래그가 많은 경우:

  • 명령어의 모든 부분을 쉽게 볼 수 있도록 여러 줄로 명령어를 나눕니다.
  • 가능한 경우 플래그의 긴 이름을 사용합니다.

예를 들어, -o--option과 같은 짧은 CLI 플래그가 있는 긴 명령어의 경우:

job1:
  script:
    - docker run
        --env SOURCE_CODE="$PWD"
        --volume "$PWD":/code
        --volume /var/run/docker.sock:/var/run/docker.sock
        "$CODE_QUALITY_IMAGE" /code

또한 |> YAML 연산자를 사용하여 다중 줄 명령어를 분할할 수 있습니다.

주석을 사용하여 템플릿 설명

새 파일 메뉴에서 템플릿 내용에 액세스할 수 있으며, 여기가 사용자가 템플릿에 대한 정보를 볼 수 있는 유일한 장소일 수 있습니다. 따라서 템플릿 자체에 템플릿의 동작을 명확히 문서화하는 것이 중요합니다.

다음 가이드라인은 제출된 모든 템플릿에 기대되는 기본 주석을 다루고 있습니다. 사용자나 템플릿 리뷰어들을 도울 수 있는 경우 추가 주석을 추가하세요.

요구사항과 기대 동작 설명

파일 맨 위의 # 주석에 템플릿의 사용 방법에 대한 세부 정보를 제공합니다. 이에는 다음이 포함됩니다:

  • 리포지터리/프로젝트 요구사항
  • 기대 동작
  • 사용자가 사용하기 전에 편집해야 하는 부분
  • 템플릿을 구성 파일에 복사하여 사용해야 하는지, 또는 이미 있는 파이프라인에서 include 키워드를 사용하여 사용해야 하는지
  • 프로젝트의 CI/CD 설정에 저장해야 하는 변수가 있는지
# ABC 서버를 사용하는 애플리케이션을 게시하기 위해 이 템플릿을 사용합니다.
# 이 템플릿을 새 `.gitlab-ci.yml` 파일에 복사하여 붙여넣을 수 있습니다.
# 기존의 `.gitlab-ci.yml` 파일에 `include:` 키워드를 사용하여 이 템플릿을 추가해서는 안 됩니다.
#
# 요구사항:
# - /content에 저장된 ABC 프로젝트
# - /test에 테스트가 있는 ABC 프로젝트
# - 프로젝트 CI/CD 설정에 ABC-PASSWORD라는 이름의 CI/CD 변수가 있어야 합니다. 값은
#   ABC 서버로 배포하는 데 사용되는 암호여야 합니다.
# - 포트 12345에서 수신 대기 중인 ABC 서버가 있어야 합니다.
#
# 123번째 줄에 URL을 여러분의 ABC 서버와 포트를 가리키도록 변경해야 합니다.
#
# 자세한 내용은 https://gitlab.com/example/abcserver/README.md를 참조하세요.

job1:
  ...

템플릿 변수가 템플릿 동작에 미치는 영향 설명

템플릿이 변수를 사용하는 경우, 해당 변수가 처음 정의된 곳에서 # 주석으로 설명합니다. 변수가 이미 명백한 경우에는 해당 주석을 생략할 수 있습니다.

variables:                        # 여기에 주석을 추가하는 것이 좋습니다. 예시: 
  TEST_CODE_PATH: <path/to/code>  # Ruby 스펙에 대한 상대 경로로 이 변수를 업데이트하세요

job1:
  variables:
    ERROR_MESSAGE: "The $TEST_CODE_PATH path is invalid"  # (이미 명확하기 때문에 주석이 필요하지 않습니다)
  script:
    - echo ${ERROR_MESSAGE}

로컬이 아닌 변수에는 대문자로 이름 지정

프로젝트 설정을 통해 변수를 제공하거나 variables 키워드를 통해 변수가 제공될 것으로 예상되는 경우, 해당 변수는 단어 사이에 언더스코어(_)로 구분하고 대문자로 작성해야 합니다.

.with_login:
  before_script:
    # SECRET_TOKEN은 프로젝트 설정을 통해 제공되어야 합니다
    - docker login -u my-user -p "$SECRET_TOKEN my-registry

변수가 script 키워드 중 하나에서 로컬로 정의된 경우 소문자 이름을 선택적으로 사용할 수 있습니다.

job1:
  script:
    - response="$(curl "https://example.com/json")"
    - message="$(echo "$response" | jq -r .message)"
    - 'echo "서버 응답: $message"'

하위 호환성

템플릿이 include:template: 키워드를 사용하여 동적으로 포함될 수 있습니다. 기존 템플릿을 변경하는 경우 기존 프로젝트의 CI/CD가 중단되지 않도록 해야 합니다.

예를 들어, 템플릿에서 작업 이름을 변경하면 기존 프로젝트의 파이프라인이 중단될 수 있습니다. Performance.gitlab-ci.yml이라는 템플릿이 있는 경우 다음 내용으로 구성되어 있을 수 있습니다:

performance:
  image: registry.gitlab.com/gitlab-org/verify-tools/performance:v0.1.0
  script: ./performance-test $TARGET_URL

그리고 사용자가 performance 작업에 인수를 전달하여 해당 템플릿을 포함하는 경우가 있다고 가정해봅시다. 이는 사용자가 고유의 .gitlab-ci.yml 파일에서 performance 작업에 TARGET_URL이라는 변수 값을 전달함으로써 수행될 수 있습니다:

include:
  template: Performance.gitlab-ci.yml

performance:
  variables:
    TARGET_URL: https://awesome-app.com

이 경우, 템플릿의 작업 이름 performancebrowser-performance로 변경하면 사용자의 .gitlab-ci.yml 파일이 실제로 린트 오류를 일으킬 수 있습니다. 왜냐하면 더는 performance라는 작업이 템플릿에 없기 때문에 오류가 발생하기 때문입니다. 따라서 사용자는 워크플로를 방해하게 됩니다.

버전 관리 섹션을 읽어서 위험을 최소화하는 방법에 대해 알아보세요.

버전 관리

현재 템플릿이 의존하는 기존 프로젝트에 영향을 미치지 않고 변경사항을 도입하려면 stablelatest 버전 관리를 사용하세요.

안정 버전 템플릿은 일반적으로 주요 버전 릴리스에서만 변경 사항이 도입됩니다. 반면 최신 버전 템플릿은 언제든지 변경 사항이 도입될 수 있습니다. 주요 릴리스에서 최신 템플릿이 안정 템플릿으로 변경됩니다(최신 템플릿은 삭제될 수 있음)

새로운 최신 템플릿을 추가하는 것은 안전하지만 유지 관리 부담이 따릅니다.

  • GitLab은 안정 버전을 최신 버전으로 덮어쓰기 위해 다음 주요 GitLab 릴리스에서 안정 버전 템플릿 내용을 덮어쓸 DRI를 선택해야 합니다. 이 DRI는 변경에 문제가 있는 사용자를 지원할 책임을 집니다.
  • 새로운 비호환성 변경을 도입하면 안정 버전과 최신 버전을 모두 업데이트해야 합니다.
  • 많은 사용자가 계속해서 최신 템플릿의 존재를 요구하는 경우 최신 템플릿은 예상보다 오랫동안 남게 될 수 있습니다.

새로운 최신 템플릿을 추가하기 전에 안정 템플릿에 변경사항을 도입할 수 있는지 확인하세요. 비호환성 변경이라도 제안된 용도가 복사 및 붙여넣기로만 사용되는 경우 안정 버전을 직접 변경할 수 있습니다. 비호환성 변경이 있는 안정 템플릿을 마이너 마일스톤에서 변경하기 전에 다음을 확인하세요:

안정 버전

안정 CI/CD 템플릿은 주요 버전 릴리스에서만 비호환성 변경이 도입되는 템플릿입니다. 예를 들어 15.0과 같은 메이저 마일스톤 릴리스에서 사용 가능한 최신 템플릿을 복사하여 새로운 안전 버전 템플릿을 만들 수 있습니다. 모든 비호환성 변경은 Deprecated 페이지에 공지해야 합니다.

비호환성 변경이 없는 변경사항을 최신 템플릿으로 동기화하려면 마이너 GitLab 릴리스(예: 15.1)에서 변경할 수 있습니다.

옵션 15.1과 같은 마이너 릴리스에서 안정 CI/CD 템플릿 버전을 변경할 수 있습니다.

최신 버전

latest로 표시된 템플릿은 파괴적인 변경 사항과 관계 없이 어떠한 릴리스에서도 업데이트할 수 있습니다. 템플릿 이름에 .latest를 추가하면 최신 버전으로 간주됩니다. 예를 들어 Jobs/Deploy.latest.gitlab-ci.yml와 같이 최신 버전인 경우입니다.

파괴적인 변경을 도입할 때, 업그레이드 경로를 반드시 테스트하고 문서화해야 합니다. 일반적으로 최신 템플릿을 가장 좋은 옵션으로 홍보해서는 안 됩니다. 예상치 못한 문제로 사용자를 놀라게 할 수 있기 때문입니다.

latest 템플릿이 아직 존재하지 않는 경우, 안정적인 템플릿을 복사할 수 있습니다.

이전 안정적인 템플릿을 포함하는 방법

사용자는 현재 GitLab 패키지에 묶이지 않은 이전 안정적인 템플릿을 사용하고 싶어할 수 있습니다. 예를 들어, GitLab 15.0과 GitLab 16.0의 안정적인 템플릿이 너무 다르기 때문에 사용자가 GitLab 16.0으로 업그레이드한 후에도 GitLab 15.0 템플릿을 계속 사용하려는 경우입니다.

템플릿이나 문서에 이전 템플릿 버전을 포함하는 방법에 대해 설명을 추가할 수 있습니다. 다른 템플릿이 include: template로 포함되면 이것을 include: remote와 결합할 수 있습니다.

# v14에 포함되지 않은 v13 안정적인 템플릿을 사용하려면 특정 템플릿을 가져오려면
# `include:remote` 키워드를 사용하여 원격 템플릿 리포지터리에서 해당 템플릿을 가져옵니다.
# GitLab 본사 프로젝트에서 가져오려면 다음 URL 형식을 사용하십시오:
# https://gitlab.com/gitlab-org/gitlab/-/raw/<version>/lib/gitlab/ci/templates/<template-name>
include:
  - template: Auto-DevOps.gitlab-ci.yml
  - remote: https://gitlab.com/gitlab-org/gitlab/-/raw/v13.0.1-ee/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml

더 읽을 거리

GitLab CI/CD 템플릿에 버전 관련 개념을 도입하는 개방된 이슈가 있습니다. 진행 상황을 확인하려면 해당 이슈를 확인할 수 있습니다.

테스트

각 CI/CD 템플릿은 게시해도 안전한지 확인하기 위해 테스트해야 합니다.

매뉴얼 QA

템플릿을 데모 프로젝트에서 테스트하는 것은 언제나 좋은 실천 방법입니다. 아래 단계를 따라하세요:

  1. https://gitlab.com에 공개 샘플 프로젝트를 만듭니다.
  2. 제안된 템플릿이 포함된 .gitlab-ci.yml을 프로젝트에 추가합니다.
  3. 파이프라인을 실행하고 모든 가능한 경우(Merge Request 파이프라인, 일정 등)에 모든 것이 제대로 실행되는지 확인합니다.
  4. 새로운 템플릿을 추가하는 Merge Request의 설명에 프로젝트에 대한 링크를 추가합니다.

이 정보는 리뷰어가 템플릿이 안전하게 Merge될 수 있도록 확인하는 데 유용합니다.

UI에서 새 템플릿을 선택할 수 있는지 확인

특정 디렉터리에 있는 템플릿 역시 새 파일 UI에서 선택할 수 있습니다. 이러한 디렉터리에 템플릿을 추가할 때 드롭다운 디렉터리에 올바르게 나타나는지 확인합니다:

CI/CD 템플릿 선택

RSpec 테스트 작성

파이프라인 작업이 올바르게 생성되는지 확인하기 위해 RSpec 테스트를 작성해야 합니다.

  1. spec/lib/gitlab/ci/templates/<template-category>/<template-name>_spec.rb에 테스트 파일을 추가합니다.
  2. Ci::CreatePipelineService를 통해 파이프라인 작업이 올바르게 생성되는지를 테스트합니다.

파괴적인 변경 사항 확인

최신 템플릿에 파괴적인 변경 사항을 도입할 때 다음을 수행해야 합니다:

  1. 안정적인 템플릿에서의 업그레이드 경로를 테스트합니다.
  2. 사용자가 어떤 종류의 오류를 만나는지 확인합니다.
  3. 이를 문서화하여 문제 해결 가이드로 작성합니다.

이 정보는 안정적인 템플릿이 주요 버전의 GitLab 릴리스에서 업데이트될 때 사용자에게 중요합니다.

메트릭 추가

모든 CI/CD 템플릿에는 사용 추적을 위해 메트릭이 정의되어 있어야 합니다. CI/CD 템플릿 월별 사용 보고서 Sisense (GitLab 팀 멤버 전용)에서 확인할 수 있습니다. 단일 템플릿에 대한 그래프를 보려면 해당 템플릿을 선택하십시오.

새 템플릿에 대한 메트릭 정의를 추가하려면:

  1. GitLab GDK를 설치하고 시작합니다.
  2. GDK의 gitlab 디렉터리에서 새 템플릿이 포함된 브랜치를 확인합니다.
  3. 새 템플릿 이벤트 이름을 주간 및 월간 CI/CD 템플릿 총 수 메트릭에 추가합니다:
  4. 위에서와 같은 이벤트 이름을 사용하여 다음 명령을 사용하여 새로운 메트릭 정의를 추가합니다:

    bundle exec rails generate gitlab:usage_metric_definition:redis_hll ci_templates <template_metric_event_name>
    

    출력은 다음과 같아야 합니다:

    $ bundle exec rails generate gitlab:usage_metric_definition:redis_hll ci_templates p_ci_templates_my_template_name
          create  config/metrics/counts_7d/20220120073740_p_ci_templates_my_template_name_weekly.yml
          create  config/metrics/counts_28d/20220120073746_p_ci_templates_my_template_name_monthly.yml
    
  5. 다음과 같이 두 파일을 편집합니다:

    • name:performance_indicator_type:: 삭제합니다 (필요 없음).
    • introduced_by_url:: 템플릿을 추가하는 MR의 URL입니다.
    • data_source:: redis_hll로 설정합니다.
    • description: 이 메트릭이 카운트하는 내용에 대한 간단한 설명을 추가합니다. 예: 최신 Auto Deploy 템플릿을 사용하는 파이프라인 개수
    • product_*: 섹션, 스테이지, 그룹 및 기능 카테고리에 따라 설정합니다. 메트릭 사전 가이드에서 도움을 요청할 수 있습니다.

      위 키워드의 구체적인 사용법을 모르는 경우 MR에서 도움을 요청할 수 있습니다.

    • 각 파일에 끝에 다음을 추가합니다:

      options:
        events:
          - p_ci_templates_my_template_name
      
  6. 변경 사항을 커밋하고 푸시합니다.

예를 들어, 이것은 5분 Production App 템플릿에 대한 메트릭 구성 파일입니다:

보안

템플릿에는 악성 코드가 포함될 수 있습니다. 예를 들어 작업 내에 export 쉘 명령어를 포함하는 템플릿은 실수로 작업 로그에서 비밀 프로젝트 CI/CD 변수를 노출시킬 수 있습니다. 안전성 여부를 확신할 수 없다면 보안 전문가에게 상호 검증을 요청해야 합니다.

CI/CD 템플릿 Merge Request에 기여하기

CI/CD 템플릿 MR이 생성되고 ci::templates로 레이블이 지정된 후, DangerBot은 코드를 검토할 수 있는 리뷰어와 유지 보수자 하나씩을 제안합니다. Merge Request이 검토를 받을 준비가 되면, 언급하여 리뷰어에게 CI/CD 템플릿 변경 사항을 검토해 달라고 요청하세요. CI/CD 템플릿 MR에 DangerBot 작업 추가 내용은 Merge Request의 상세정보에서 확인할 수 있습니다.