CI 구성 내부

Workflow 규칙

GitLab 프로젝트의 파이프라인은 GitLab CI/CD의 workflow:rules 키워드 기능을 사용하여 생성됩니다.

다음 시나리오에 대해 파이프라인이 항상 생성됩니다:

  • main 브랜치, 예약, 푸시, 머지 등을 포함합니다.
  • MR(Merge requests).
  • 태그.
  • Stable, auto-deploy, 보안 브랜치.

파이프라인이 생성되도록 하는 것은 다음 CI/CD 변수에도 영향을 받습니다:

  • $FORCE_GITLAB_CI가 설정되어 있으면 파이프라인이 생성됩니다. 권장되지 않음. Avoid $FORCE_GITLAB_CI를 참조하세요.
  • $GITLAB_INTERNAL이 설정되어 있지 않으면 파이프라인이 생성되지 않습니다.

다른 경우에는 파이프라인이 생성되지 않습니다(예: MR이 없는 브랜치로 푸시하는 경우).

이 workflow 규칙의 근본은 .gitlab-ci.yml에 정의되어 있습니다.

$FORCE_GITLAB_CI 사용을 피하십시오

파이프라인이 매우 복잡하고 우리가 어떤 종류의 파이프라인을 트리거할지 명확히 이해해야 합니다. 우리는 어떤 작업을 실행해야 하고 어떤 작업을 실행하면 안 되는지 알아야 합니다.

만약 우리가 $FORCE_GITLAB_CI를 사용하여 파이프라인을 강제적으로 트리거한다면, 우리는 실제로 어떤 종류의 파이프라인인지 모릅니다. 결과적으로 우리가 원하는 작업을 실행하지 않거나, 우리가 관심을 가지지 않는 너무 많은 작업을 실행할 수 있습니다.

더 많은 컨텍스트와 배경은 다음에서 찾을 수 있습니다: Avoid blanket changes to avoid unexpected run

현재 우리가 이것을 사용하고 있는 목록과, $FORCE_GITLAB_CI 사용지에서 이것으로부터 이동하려고 해야 합니다.

$FORCE_GITLAB_CI를 사용하지 않고 파이프라인을 활성화하는 방법은 다음 섹션에서 설명하겠습니다.

$FORCE_GITLAB_CI 대체 옵션

기본적으로, 우리는 다른 변수를 사용하여 다른 파이프라인을 활성화합니다. 이를 수행하는 예시는 $START_AS_IF_FOSS입니다. Cross project FOSS pipeline을 트리거하고 싶을 때, 우리는 $START_AS_IF_FOSS를 설정하고, $ENABLE_RSPEC_UNIT, $ENABLE_RSPEC_SYSTEM 등의 일련의 다른 변수와 함께 각 작업을 활성화합니다. 이를 통해 as-if-foss cross project downstream pipeline에서 실행하려는 각 작업을 활성화합니다.

이러한 접근 방식의 장점은 $FORCE_GITLAB_CI 대신에 파이프라인을 어떻게 실행할지에 대한 완전한 통제력을 가질 수 있다는 것입니다. 왜냐하면 $START_AS_IF_FOSS는 이러한 목적으로만 사용되기 때문에, 이 변수 아래에서 파이프라인이 어떻게 동작하도록 변경해도 다른 종류의 파이프라인에는 영향을 주지 않으며, $FORCE_GITLAB_CI를 사용하면 우리는 파이프라인이 정확히 무엇인지 알 수 없습니다. 왜냐하면 이것은 여러 목적으로 사용되기 때문입니다.

기본 이미지

기본 이미지가 .gitlab-ci.yml에 정의되어 있습니다.

이는 Ruby, Go, Git, Git LFS, Chrome, Node, Yarn, PostgreSQL, Graphics Magick을 포함합니다.

우리 파이프라인에서 사용되는 이미지는 gitlab-org/gitlab-build-images 프로젝트에 구성되어 있으며, 이는 백업을 위해 gitlab/gitlab-build-images로 push-mirrored됩니다.

빌드 이미지의 현재 버전은 “GitLab에서 사용”에서 찾을 수 있습니다.

기본 변수

사전 정의된 CI/CD 변수에 추가하여, 각 파이프라인에는 .gitlab-ci.yml에 정의된 기본 변수가 포함됩니다.

단계

현재 사용 중인 단계는 다음과 같습니다:

  • sync: 이 단계는 gitlab-org/gitlab에서 gitlab-org/gitlab-foss로의 변경 사항을 동기화하는 데 사용됩니다.
  • prepare: 이 단계에는 이후 단계에서 필요한 아티팩트를 준비하는 작업이 포함됩니다.
  • build-images: 이 단계에는 이후 단계 또는 downstream 파이프라인에서 필요한 Docker 이미지를 준비하는 작업이 포함됩니다.
  • fixtures: 이 단계에는 frontend 테스트에 필요한 픽스처를 준비하는 작업이 포함됩니다.
  • lint: 이 단계에는 린트 및 정적 분석 작업이 포함됩니다.
  • test: 이 단계에는 대부분의 테스트 및 DB/migration 작업이 포함됩니다.
  • post-test: 이 단계는 test 단계 작업에서 리포트를 작성하거나 데이터를 수집하는 작업이 포함됩니다(예: 커버리지, Knapsack 메타데이터 등).
  • review: 이 단계에는 CNG 이미지를 빌드하고, 리뷰 앱에서 엔드 투 엔드 테스트를 실행하고(자세한 내용은 리뷰 앱을 참조), Docs Review App 작업이 포함됩니다.
  • qa: 이 단계에는 review 단계에 배포된 리뷰 앱에 대한 QA 작업이 포함됩니다.
  • post-qa: 이 단계는 qa 단계에서 리포트를 작성하거나 데이터를 수집하는 작업이 포함됩니다(예: 리뷰 앱 성능 리포트).
  • pages: 이 단계에는 다양한 리포트를 GitLab Pages로 배포하는 작업이 포함됩니다(예: coverage-ruby, webpack-report(다음에서 찾을 수 있습니다 https://gitlab-org.gitlab.io/gitlab/webpack-report/, 다만 배포에 문제가 있습니다)).
  • notify: 이 단계에는 여러 실패 사항을 Slack에 알리는 작업이 포함됩니다.

의존성 프록시

일부 작업에서는 Docker Hub에서 이미지를 사용하며, 이미지 경로의 접두사로 ${GITLAB_DEPENDENCY_PROXY_ADDRESS}를 사용하여 이미지를 의존성 프록시에서 가져오도록 합니다. 기본적으로, 이 변수는 ${GITLAB_DEPENDENCY_PROXY}의 값에서 설정됩니다.

${GITLAB_DEPENDENCY_PROXY}${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/로 정의된 그룹 CI/CD 변수로 gitlab-org에 정의됩니다. 이것은 우리가 다음과 같이 정의된 이미지를 사용할 때 의존성 프록시로부터 가져옴을 의미합니다:

image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}alpine:edge

gitlab-org 그룹 내의 프로젝트는 의존성 프록시에서 가져오고, 다른 개인 네임스페이스나 그룹에 속한 포크는 ${GITLAB_DEPENDENCY_PROXY}가 거기에도 정의되어 있지 않은 한 Docker Hub로 되돌아갑니다.

프로젝트 액세스 토큰 사용자에 의해 파이프라인이 시작될 때의 작업 방법

파이프라인이 Project 액세스 토큰 사용자(예: release-tools approver bot 사용자로, 이 사용자는 주 프로젝트에서 사용되는 Gitaly 버전을 자동으로 업데이트함)에 의해 시작되면, Dependency proxy에 접근할 수 없습니다 그리고 작업은 "docker+machine" executor 단계에서 실패합니다. 이 문제를 해결하기 위해, 해당 경우에는 ${GITLAB_DEPENDENCY_PROXY_ADDRESS} 변수를 재정의하여 Dependency proxy를 사용하지 않도록 하는 특별한 workflow rule이 있습니다.

- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $GITLAB_USER_LOGIN =~ /project_\d+_bot\d*/'
  variables:
    GITLAB_DEPENDENCY_PROXY_ADDRESS: ""

참고: .gitlab-ci.yml 변수보다 그룹 수준의 변수가 우선순위가 더 높기 때문에, ${GITLAB_DEPENDENCY_PROXY} 변수를 직접적으로 재정의하지는 않습니다.

공통 작업 정의

대부분의 작업은 일부 CI 정의확장하며, 이들은 단일 구성 키워드에 대해 스코프가 지정된 .gitlab/ci/global.gitlab-ci.yml에 정의되어 있습니다.

작업 정의 설명
.default-retry unknown_failure, api_failure, runner_system_failure, job_execution_timeout, 또는 stuck_or_timeout_failure가 발생했을 때 작업을 재시도할 수 있도록 합니다.
.default-before_script 작업이 데이터베이스가 실행 중인 Ruby/Rails 작업(예: 테스트)에 필요한 기본 before_script 정의를 사용할 수 있도록 합니다.
.repo-from-artifacts 작업이 .clone-gitlab-repo에서 아티팩트에 있는 리포지토리를 가져와 클론하지 않도록 합니다. 이것은 GitLab.com Gitaly 부하를 줄이고 아티팩트에서 다운로드하는 것이 클론보다 빠른 속도로 되므로 속도도 약간 향상시킬 것으로 예상됩니다. 아티팩트를 사용하여 다운로드하는 것이기 때문에 needs: []를 가진 작업에서는 사용하지 않도록 주의해야 합니다. 그렇지 않으면 보통 가능한 빨리 시작하도록 하려고 할 때 보다 더 늦게 시작하므로 클론만 하도록 사용하는 것이 좋습니다. 이 동작은 CI_FETCH_REPO_GIT_STRATEGY를 통해 제어할 수 있습니다. 자세한 내용은 Gitaly로부터 클론/가져오는 것 대신 아티팩트를 통해 리포지토리 가져오기를 참조하십시오.
.setup-test-env-cache 작업이 후속 Ruby/Rails 작업을 위한 테스트 환경을 설정하기에 적합한 기본 cache 정의를 사용할 수 있도록 합니다.
.ruby-cache Ruby 작업에 적합한 기본 cache 정의를 사용할 수 있도록 합니다.
.static-analysis-cache 정적 분석 작업에 적합한 기본 cache 정의를 사용할 수 있도록 합니다.
.ruby-gems-coverage-cache 커버리지 작업에 적합한 기본 cache 정의를 사용할 수 있도록 합니다.
.qa-cache QA 작업에 적합한 기본 cache 정의를 사용할 수 있도록 합니다.
.yarn-cache yarn install을 수행하는 프론트엔드 작업에 적합한 기본 cache 정의를 사용할 수 있도록 합니다.
.assets-compile-cache 에셋을 컴파일하는 프론트엔드 작업에 적합한 기본 cache 정의를 사용할 수 있도록 합니다.
.use-pg14 postgres 14, redis, 및 rediscluster 서비스를 사용할 수 있도록 합니다(서비스의 특정 버전은 .gitlab/ci/global.gitlab-ci.yml에 정의되어 있습니다).
.use-pg14-ee .use-pg14와 동일하지만 elasticsearch 서비스도 사용합니다(서비스의 특정 버전은 .gitlab/ci/global.gitlab-ci.yml에 정의되어 있습니다).
.use-pg15 postgres 15, redis, 및 rediscluster 서비스를 사용할 수 있도록 합니다(서비스의 특정 버전은 .gitlab/ci/global.gitlab-ci.yml에 정의되어 있습니다).
.use-pg15-ee .use-pg15와 동일하지만 elasticsearch 서비스도 사용합니다(서비스의 특정 버전은 .gitlab/ci/global.gitlab-ci.yml에 정의되어 있습니다).
.use-pg16 postgres 16, redis, 및 rediscluster 서비스를 사용할 수 있도록 합니다(서비스의 특정 버전은 .gitlab/ci/global.gitlab-ci.yml에 정의되어 있습니다).
.use-pg16-ee .use-pg16와 동일하지만 elasticsearch 서비스도 사용합니다(서비스의 특정 버전은 .gitlab/ci/global.gitlab-ci.yml에 정의되어 있습니다).
.use-kaniko kaniko 도구를 사용하여 Docker 이미지를 빌드할 수 있도록 합니다.
.as-if-foss FOSS_ONLY='1' CI/CD 변수를 설정하여 FOSS 프로젝트처럼 시뮬레이션합니다.
.use-docker-in-docker Docker in Docker를 사용할 수 있도록 합니다. 자세한 내용은 CI/CD 구성 관련 핸드북을 참조하세요.

rules, if: 조건 및 changes: 패턴

우리는 rules 키워드를 광범위하게 사용하고 있습니다.

모든 rules 정의는 rules.gitlab-ci.yml에 정의되어 있으며, 그런 다음 개별 작업에서 extends를 통해 포함됩니다.

rules 정의는 if: 조건 및 changes: 패턴으로 구성되어 있으며, 이는 또한 rules.gitlab-ci.yml에 정의되어 있으며 YAML 앵커를 통해 rules 정의에 포함됩니다.

if: 조건

if: 조건 설명 노트
if-not-canonical-namespace 프로젝트가 정규(gitlab-org/gitlab-cn/) 또는 보안(gitlab-org/security) 네임스페이스에 없는 경우 일치합니다. forks를 위한 작업 만들기 (예: when: on_success 또는 when: manual 사용) 또는 forks의 경우 작업 만들지 않기 (예: when: never 사용).
if-not-ee 프로젝트가 EE가 아닌 경우 일치합니다 (즉, 프로젝트 이름이 gitlab 또는 gitlab-ee가 아닌 경우). FOSS 프로젝트에만 작업 만들기 (예: when: on_success 또는 when: manual 사용) 또는 프로젝트가 EE인 경우 작업 만들지 않기 (예: when: never 사용).
if-not-foss 프로젝트가 FOSS가 아닌 경우 일치합니다 (즉, 프로젝트 이름이 gitlab-foss, gitlab-ce, 또는 gitlabhq가 아닌 경우). EE 프로젝트에만 작업 만들기 (예: when: on_success 또는 when: manual 사용) 또는 프로젝트가 FOSS인 경우 작업 만들지 않기 (예: when: never 사용).
if-default-refs 파이프라인이 master, main, /^[\d-]+-stable(-ee)?$/ (안정적인 브랜치), /^\d+-\d+-auto-deploy-\d+$/ (자동 배포 브랜치), /^security\// (보안 브랜치), 병합 요청, 및 태그를 위한 것인 경우 일치합니다. 이 기본 구성으로 브랜치에 대한 작업이 생성되지 않음에 유의하세요.
if-master-refs 현재 브랜치가 master 또는 main인 경우 일치합니다.  
if-master-push 현재 브랜치가master 또는 main이며 파이프라인 소스가 push인 경우 일치합니다.  
if-master-schedule-maintenance 현재 브랜치가 master 또는 main이며 파이프라인이 2시간 단위로 실행되는 일정에 맞는 경우 일치합니다.  
if-master-schedule-nightly 현재 브랜치가 master 또는 main이며 파이프라인이 매일 실행되는 일정에 맞는 경우 일치합니다.  
if-auto-deploy-branches 현재 브랜치가 자동 배포 브랜치인 경우 일치합니다.  
if-master-or-tag 파이프라인이 master 또는 main 브랜치 또는 태그를 위한 것인 경우 일치합니다.  
if-merge-request 파이프라인이 병합 요청을 위한 것인 경우 일치합니다.  
if-merge-request-title-as-if-foss 파이프라인이 병합 요청을 위한 것이고 MR에 label ~"pipeline:run-as-if-foss"가있는 경우 일치합니다.  
if-merge-request-title-update-caches 파이프라인이 병합 요청을 위한 것이고 MR에 label ~"pipeline:update-cache"가있는 경우 일치합니다.  
if-merge-request-labels-run-all-rspec 파이프라인이 병합 요청을 위한 것이고 MR에 label ~"pipeline:run-all-rspec"가있는 경우 일치합니다.  
if-merge-request-labels-run-cs-evaluation 파이프라인이 병합 요청을 위한 것이고 MR에 label ~"pipeline:run-CS-evaluation"이있는 경우 일치합니다.  
if-security-merge-request 파이프라인이 보안 병합 요청을 위한 것인 경우 일치합니다.  
if-security-schedule 보안 예약된 파이프라인을 위한 것이면 일치합니다.  
if-nightly-master-schedule $NIGHTLY가 설정된 master 예약 파이프라인을 위한 것이면 일치합니다.  
if-dot-com-gitlab-org-schedule GitLab.com의 gitlab-org 그룹에 대한 예약된 파이프라인을 생성으로 제한합니다.  
if-dot-com-gitlab-org-master GitLab.com의 gitlab-org 그룹에 대한 master 또는 main 브랜치에 대한 작업 생성으로 제한합니다.  
if-dot-com-gitlab-org-merge-request GitLab.com의 gitlab-org 그룹에 대한 병합 요청에 대한 작업 생성으로 제한합니다.  
if-dot-com-ee-schedule GitLab.com의 gitlab-org/gitlab 프로젝트에 대한 예약된 파이프라인을 위한 작업을 제한합니다.  

changes: 패턴

changes: 패턴 설명
ci-patterns CI 구성 관련 변경 사항에 대해 작업 생성
ci-build-images-patterns build-images 단계와 관련된 CI 구성 관련 변경 사항에 대해 작업 생성
ci-review-patterns review 단계와 관련된 CI 구성 관련 변경 사항에 대해 작업 생성
ci-qa-patterns qa 단계와 관련된 CI 구성 관련 변경 사항에 대해 작업 생성
yaml-lint-patterns YAML 관련 변경 사항에 대해 작업 생성
docs-patterns 문서 관련 변경 사항에 대해 작업 생성
frontend-dependency-patterns 프론트엔드 종속성 업데이트 시 작업 생성 (예: package.jsonyarn.lock 변경)
frontend-patterns-for-as-if-foss FOSS에 영향을 미치는 프론트엔드 관련 변경에 대해 작업 생성
backend-patterns 백엔드 관련 변경 사항에 대해 작업 생성
db-patterns DB 관련 변경 사항에 대해 작업 생성
backstage-patterns 백스테이지 관련 변경 사항에 대해 작업 생성 (예: Danger, fixtures, RuboCop, specs)
code-patterns 코드 관련 변경 사항에 대해 작업 생성
qa-patterns QA 관련 변경 사항에 대해 작업 생성
code-backstage-patterns code-patternsbackstage-patterns의 조합에 대해 작업 생성
code-qa-patterns code-patternsqa-patterns의 조합에 대해 작업 생성
code-backstage-qa-patterns code-patterns, backstage-patterns, 및 qa-patterns의 조합에 대해 작업 생성
static-analysis-patterns 정적 분석 관련 구성 변경 사항에 대해 작업 생성

Best Practices

extends:, <<: *xyz (YAML anchors) 또는 !reference 사용 시기

참조

핵심 내용

  • 해시를 확장해야 하는 경우, extends를 사용해야 합니다.
  • 배열을 확장해야 하는 경우, !reference 또는 YAML anchors를 마지막 수단으로 사용해야 합니다.
  • 보다 복잡한 경우(예: 배열 내의 해시 확장, 해시 내의 배열 확장 등)에는 !reference 또는 YAML anchors를 사용해야 합니다.

extendsYAML anchors가 할 수 있는 것은?

extends
  • 해시에 대한 깊은 병합
  • 배열에 대한 병합 불가. 덮어씁니다 (원본)
YAML anchors
  • 해시에 대한 깊은 병합 불가, 그러나 해시를 확장하는 데 사용할 수 있습니다 (아래 예시 참조)
  • 배열에 대한 병합 불가, 그러나 배열을 확장하는 데 사용할 수 있습니다 (아래 예시 참조)

훌륭한 예시

다음 예시는 !referenceYAML anchors를 사용하여 복잡한 YAML 데이터 구조를 확장하는 방법을 보여줍니다:

.strict-ee-only-rules:
  # `rules`는 해시 배열입니다
  rules:
    - if: '$CI_PROJECT_NAME !~ /^gitlab(-ee)?$/ '
      when: never

# `if-security-merge-request`는 해시입니다
.if-security-merge-request: &if-security-merge-request
  if: '$CI_PROJECT_NAMESPACE == "gitlab-org/security"'

# `code-qa-patterns`는 배열입니다
.code-qa-patterns: &code-qa-patterns
  - "{package.json,yarn.lock}"
  - ".browserslistrc"
  - "babel.config.js"
  - "jest.config.{base,integration,unit}.js"

.qa:rules:as-if-foss:
  rules:
    # 우리는 해시 배열을 직접 사용하여 'rules' 배열을 확장합니다
    - !reference [".strict-ee-only-rules", rules]
    # 단일 배열 항목을 해시로 확장합니다
    - <<: *if-security-merge-request
      # `changes`는 배열이므로 전체 배열을 전달합니다
      changes: *code-qa-patterns

qa:selectors-as-if-foss:
  # .qa:rules:as-if-foss에서 규칙을 이 작업에 포함합니다
  extends:
    - .qa:rules:as-if-foss

.fast-no-clone-job 작업 확장

카노니컬 프로젝트의 브랜치를 다운로드하는 데 20 ~ 30초가 소요됩니다.

일부 작업은 GitLab API를 통해 다운로드할 파일이 제한적입니다.

작업에 다음 패턴을 추가하여 작업에서 git clone/git fetch을 건너뛸 수 있습니다.

시나리오 1: 작업에서 before_script가 정의되지 않은 경우

이 패턴은 작업에서 확장하는 부모 섹션에도 적용됩니다.

.fast-no-clone-job를 확장하기만 하면 됩니다:

변경 전:

  # 참고: 작업에 `extends:`가 없습니다
  a-job:
    script:
      - source scripts/rspec_helpers.sh scripts/slack
      - echo "git clone이 필요하지 않습니다!"

변경 후:

  # 참고: 작업에 `extends:`가 없습니다
  a-job:
    extends:
      - .fast-no-clone-job
    variables:
      FILES_TO_DOWNLOAD: >
        scripts/rspec_helpers.sh
        scripts/slack
    script:
      - source scripts/rspec_helpers.sh scripts/slack
      - echo "git clone이 필요하지 않습니다!"

시나리오 2: 작업 또는 확장된 작업에서 이미 before_script 블록이 정의된 경우

이 시나리오에서는 다음을 수행해야 합니다:

  1. 첫 번째 시나리오와 마찬가지로 .fast-no-clone-job을 확장합니다 (FILES_TO_DOWNLOAD 변수를 다른 변수와 병합함)
  2. 이 작업에 사용하는 before_script에서 .fast-no-clone-jobbefore_script 섹션을 참조합니다.

변경 전:

  .base-job:
    before_script:
      echo "안녕하세요 from .base-job"

  a-job:
    extends:
      - .base-job
    script:
      - source scripts/rspec_helpers.sh scripts/slack
      - echo "git clone이 필요하지 않습니다!"

변경 후:

  .base-job:
    before_script:
      echo "안녕하세요 from .base-job"

  a-job:
    extends:
      - .base-job
      - .fast-no-clone-job
    variables:
      FILES_TO_DOWNLOAD: >
        scripts/rspec_helpers.sh
        scripts/slack
    before_script:
      - !reference [".fast-no-clone-job", before_script]
      - !reference [".base-job", before_script]
    script:
      - source scripts/rspec_helpers.sh scripts/slack
      - echo "git clone이 필요하지 않습니다!"

주의사항

  • 이 패턴은 레포지토리에 액세스하기 위해 git을 사용하는 스크립트에는 작동하지 않습니다. 왜냐하면 클론이나 가져오기 없이는 레포지토리가 없기 때문입니다.
  • 이 패턴을 사용하는 작업은 curl을 사용할 수 있어야 합니다.
  • 작업에서 bundle install을 실행해야 하는 경우(심지어 BUNDLE_ONLY를 사용하는 경우), 다음을 수행해야 합니다:
    • gitlab-org/gitlab 프로젝트에 저장된 젬을 다운로드합니다.
      • 이 용도로 download_local_gems 쉘 명령을 사용할 수 있습니다.
    • Gemfile, Gemfile.lockGemfile.checksum (해당하는 경우)를 포함해야 합니다.

이 패턴은 어디에 사용됩니까?

  • 현재, 이 패턴은 다음 작업에 대해 사용되며, 이러한 작업은 비공개 레포지토리를 차단하지 않습니다:
    • 다음에 대한 review-build-cng-env:
      • GITALY_SERVER_VERSION
      • GITLAB_ELASTICSEARCH_INDEXER_VERSION
      • GITLAB_KAS_VERSION
      • GITLAB_PAGES_VERSION
      • GITLAB_SHELL_VERSION
      • scripts/trigger-build.rb
      • VERSION
    • 다음에 대한 review-deploy:
      • GITALY_SERVER_VERSION
      • GITLAB_SHELL_VERSION
      • scripts/review_apps/review-apps.sh
      • scripts/review_apps/seed-dast-test-data.sh
      • VERSION
    • rspec:coverage에 대한:
      • config/bundler_setup.rb
      • Gemfile
      • Gemfile.checksum
      • Gemfile.lock
      • scripts/merge-simplecov
      • spec/simplecov_env_core.rb
      • spec/simplecov_env.rb
    • prepare-as-if-foss-env에 대한:
      • scripts/setup/generate-as-if-foss-env.rb

또한, 이 패턴이 사용될 때 항상 scripts/utils.sh가 API에서 다운로드됩니다 (이 파일에는 .fast-no-clone-job의 코드가 포함되어 있음).

Runner 태그

GitLab.com에서는 비특권적 및 특권적 러너가 모두 사용 가능합니다. gitlab-org 그룹 내 프로젝트 및 해당 프로젝트의 포크에 대해서는 작업에 다음 태그 중 하나만 추가해야 합니다.

  • gitlab-org: 작업은 무작위로 특권적 및 비특권적 러너를 사용합니다.
  • gitlab-org-docker: 작업은 특권적 러너를 사용해야 합니다. Docker-in-Docker support가 필요한 경우 gitlab-org 대신 gitlab-org-docker를 사용하세요.

gitlab-org-docker 태그는 위에서 정의된 .use-docker-in-docker 작업 내에서 추가됩니다.

포크 호환성을 보장하기 위해 gitlab-orggitlab-org-docker를 동시에 사용하지 않도록 해야 합니다. 포크의 gitlab-org 프로젝트의 경우 동시에 두 태그를 제공하면 일치하는 러너가 없기 때문에 작업이 멈출 수 있습니다.

더 많은 정보는 GitLab Repositories handbook 페이지를 참조하세요.

카노니컬 프로젝트에서 gitlab Ruby gem 사용

카노니컬 프로젝트에서 require 'gitlab'를 호출할 때, 응용프로그램을 로드할 때 (config/application.rb) 또는 테스트할 때 (spec/spec_helper.rb) $LOAD_PATHlib이 있는 경우 lib/gitlab.rb 파일이 필요합니다.

이는 위의 조건에서 gitlab gem을 로드할 수 없으며, 가능하더라도 상수 이름이 충돌하여 내부 전제를 파괴하고 무작위 오류를 발생시킬 수 있음을 의미합니다. the gitlab Ruby gem을 사용하는 스크립트를 작업하는 경우 몇 가지 주의가 필요합니다:

1 - gem의 조건부 require

잠재적인 충돌을 피하기 위해 Gitlab 상수가 정의되지 않은 경우에만 gitlab gem을 요구합니다:

# 나쁨
require 'gitlab'

# 좋음
if Object.const_defined?(:RSpec)
  # 괜찮음, 테스트 중임을 알고 있으므로 'Gitlab'을 스텁하게 될 것으로 알고 있으므로 간과
else
  require 'gitlab'

  if Gitlab.singleton_class.method_defined?(:com?)
    abort 'lib/gitlab.rb가 로드되어 있는 상태이며, 이는 더 이상 클라이언트를 로드할 수 없게 되었음을 의미하므로 진행할 수 없음'
  end
end

2 - 스펙에서 gem을 완전히 모의화

스펙에서 require 'gitlab'lib/gitlab.rb 파일을 참조할 것입니다:

# 나쁨
allow(GitLab).to receive(:a_method).and_return(...)

# 좋음
client = double('GitLab')
# 클라이언트를 쉽게 스텁화하기 위해 메서드를 반환하는 메서드를 사용하는 것을 고려하세요.
# 그런 다음 해당 메서드를 우리의 가짜 클라이언트를 반환하도록 스텁화할 수 있습니다.

# 아래에서 따르는 패턴입니다
let(:instance) { described_class.new }

allow(instance).to receive(:gitlab).and_return(client)
allow(client).to receive(:a_method).and_return(...)

인스턴스에 대한 작업을 쿼리해야 하는 경우, 다음 스니펫이 유용합니다:

# 나쁨
allow(GitLab).to receive(:pipeline_jobs).and_return(...)

# 좋음
#
# rubocop:disable RSpec/VerifiedDoubles -- 우리는 Gitlab 클라이언트를 직접로드하지 않습니다
client = double('GitLab')
allow(instance).to receive(:gitlab).and_return(client)

jobs = ['job1', 'job2']
allow(client).to yield_jobs(:pipeline_jobs, jobs)

def yield_jobs(api_method, jobs)
  messages = receive_message_chain(api_method, :auto_paginate)

  jobs.inject(messages) do |stub, job_name|
    stub.and_yield(double(name: job_name))
  end
end
# rubocop:enable RSpec/VerifiedDoubles

3 - 스크립트를 bundle exec로 호출하지 마세요

bundle exec로 실행하면 Ruby의 $LOAD_PATH가 변경되어 require 'gitlab'를 호출할 때 lib/gitlab.rb을 로드하게 됩니다:

# 나쁨
bundle exec scripts/my-script.rb

# 좋음
scripts/my-script.rb

CI 구성 테스트

이제 업데이트된 YAML 파일로 파이프라인을 시뮬레이션하여 CI 구성 변경을 확인하는 RSpec 테스트가 있습니다. 이러한 테스트 및 현재 테스트 커버리지에 대한 문서는 spec/dot_gitlab_ci/job_dependency_spec.rb에서 찾을 수 있습니다.

테스트 작동 방식

Ci::CreatePipelineService의 도움을 통해 브랜치 이름, MR 라벨, 파이프라인 소스 (스케줄링 vs 푸시), 파이프라인 유형 (병합 트레인 vs 병합 결과)과 같은 다양한 속성으로 파이프라인 생성을 시뮬레이션할 수 있습니다. 이것은 CI/CD 구성을 유효성 검사하기 위해 GitLab CI Lint API에서 사용하는 동일한 서비스입니다.

이러한 테스트는 CI 구성을 업데이트하는 머지 요청에 대해 자동으로 실행됩니다. 그러나 팀 멤버는 머지 요청에 레이블 ~"pipeline:skip-ci-validation"을 추가하여 이러한 테스트를 건너뛸 수 있습니다.

로컬에서 이러한 테스트를 실행하는 것이 권장됩니다. 가장 빠른 피드백을 제공하기 때문입니다.