GitLab CI/CD 구성 파일 최적화

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-Managed, GitLab Dedicated

GitLab CI/CD 구성 파일에서 복잡성과 중복 구성을 줄일 수 있습니다.

  • 앵커 (&), 별칭(*), 그리고 맵 병합(<<)과 같은 YAML 특정 기능을 사용하세요. 다양한 YAML 기능에 대해 더 알아보세요.
  • extends 키워드 는 더 유연하고 가독성이 좋습니다. 가능한 경우에는 ‘extends’를 사용하세요.

앵커

YAML에는 문서 전체에서 내용을 복제할 수 있는 앵커라는 기능이 있습니다.

앵커를 사용하여 속성을 복제하거나 상속하세요. 숨겨진 작업에서 앵커를 사용하여 작업의 템플릿을 제공하세요. 중복된 키가 있는 경우, 최신 포함된 키가 다른 키를 재정의합니다.

특정 경우에는 (스크립트용 YAML 앵커 참조) 다른 곳에서 정의된 여러 구성 요소로 배열을 작성하는 데 YAML 앵커를 사용할 수 있습니다. 예를 들어:

.default_scripts: &default_scripts
  - ./default-script1.sh
  - ./default-script2.sh

job1:
  script:
    - *default_scripts
    - ./job-script.sh

당신은 include 키워드를 사용할 때 여러 파일에 걸쳐 YAML 앵커를 사용할 수 없습니다. 앵커는 정의된 파일에서만 유효합니다. 서로 다른 YAML 파일에서 구성을 재사용하려면 !reference 태그extends 키워드를 사용하세요.

다음 예제는 앵커와 맵 병합을 사용합니다. .job_template 구성을 상속하는 test1test2라는 두 개의 작업을 생성하며, 각각 고유한 script로 정의됩니다:

.job_template: &job_configuration  # 'job_configuration'이라는 앵커를 정의하는 숨겨진 YAML 구성
  image: ruby:2.6
  services:
    - postgres
    - redis

test1:
  <<: *job_configuration           # 'job_configuration' 별칭의 내용 추가
  script:
    - test1 project

test2:
  <<: *job_configuration           # 'job_configuration' 별칭의 내용 추가
  script:
    - test2 project

&는 앵커의 이름을 설정하고, <<는 “주어진 해시를 현재 해시에 병합한다”는 의미이며, *는 지정된 앵커를 포함합니다(job_configuration 다시). 이 예제의 확장된 버전은 다음과 같습니다:

.job_template:
  image: ruby:2.6
  services:
    - postgres
    - redis

test1:
  image: ruby:2.6
  services:
    - postgres
    - redis
  script:
    - test1 project

test2:
  image: ruby:2.6
  services:
    - postgres
    - redis
  script:
    - test2 project

당신은 두 개의 서비스 세트를 정의하기 위해 앵커를 사용할 수 있습니다. 예를 들어 test:postgrestest:mysql.job_template에 정의된 script를 공유하지만, .postgres_services.mysql_services에 정의된 서로 다른 services를 사용합니다.

.job_template: &job_configuration
  script:
    - test project
  tags:
    - dev

.postgres_services:
  services: &postgres_configuration
    - postgres
    - ruby

.mysql_services:
  services: &mysql_configuration
    - mysql
    - ruby

test:postgres:
  <<: *job_configuration
  services: *postgres_configuration
  tags:
    - postgres

test:mysql:
  <<: *job_configuration
  services: *mysql_configuration

확장된 버전은 다음과 같습니다:

.job_template:
  script:
    - test project
  tags:
    - dev

.postgres_services:
  services:
    - postgres
    - ruby

.mysql_services:
  services:
    - mysql
    - ruby

test:postgres:
  script:
    - test project
  services:
    - postgres
    - ruby
  tags:
    - postgres

test:mysql:
  script:
    - test project
  services:
    - mysql
    - ruby
  tags:
    - dev

숨겨진 작업이 편리하게 템플릿으로 사용되고, tags: [postgres]tags: [dev]를 덮어쓰는 것을 볼 수 있습니다.

스크립트용 YAML 앵커

  • GitLab 16.9에서 도입된 stages 키워드로 앵커를 지원.

여러 작업에서 미리 정의된 명령을 사용하려면, 스크립트, before_script, after_script와 함께 YAML 앵커를 사용할 수 있습니다:

.some-script-before: &some-script-before
  - echo "먼저 이 스크립트를 실행"

.some-script: &some-script
  - echo "이 스크립트를 두 번째로 실행"
  - echo "또 이 스크립트를 실행"

.some-script-after: &some-script-after
  - echo "마지막으로 이 스크립트를 실행"

job1:
  before_script:
    - *some-script-before
  script:
    - *some-script
    - echo "이 작업만을 위한 것을 실행"
  after_script:
    - *some-script-after

job2:
  script:
    - *some-script-before
    - *some-script
    - echo "다른 작업만을 위한 것을 실행"
    - *some-script-after

extends를 사용하여 구성 섹션 재사용하기

여러 작업에서 구성을 재사용하기 위해 extends 키워드를 사용할 수 있습니다. 이는 YAML 앵커와 유사하지만 더 간단하며 extends를 include와 함께 사용할 수 있습니다.

extends는 다중 상속을 지원합니다. 추가적인 복잡성 때문에 세 단계 이상을 사용하는 것은 피해야 하지만, 열한 단계까지 사용할 수 있습니다. 다음 예제는 두 수준의 상속을 갖습니다:

.tests:
  rules:
    - if: $CI_PIPELINE_SOURCE == "push"

.rspec:
  extends: .tests
  script: rake rspec

rspec 1:
  variables:
    RSPEC_SUITE: '1'
  extends: .rspec

rspec 2:
  variables:
    RSPEC_SUITE: '2'
  extends: .rspec

spinach:
  extends: .tests
  script: rake spinach
### `extends`에서 키 제외

확장된 내용에서 키를 제외하려면 해당 키를 `null`로 할당해야 합니다. 예를 들어:

```yaml
.base:
  script: test
  variables:
    VAR1: base var 1

test1:
  extends: .base
  variables:
    VAR1: test1 var 1
    VAR2: test2 var 2

test2:
  extends: .base
  variables:
    VAR2: test2 var 2

test3:
  extends: .base
  variables: {}

test4:
  extends: .base
  variables: null

병합된 구성:

test1:
  script: test
  variables:
    VAR1: test1 var 1
    VAR2: test2 var 2

test2:
  script: test
  variables:
    VAR1: base var 1
    VAR2: test2 var 2

test3:
  script: test
  variables:
    VAR1: base var 1

test4:
  script: test
  variables: null

extendsinclude 함께 사용

다른 구성 파일에서 구성을 재사용하려면 extendsinclude를 결합하세요.

다음 예에서 included.yml 파일에 script가 정의되어 있습니다. 그런 다음 .gitlab-ci.yml 파일에서 extendsscript 내용을 참조합니다.

  • included.yml:

    .template:
      script:
        - echo Hello!
    
  • .gitlab-ci.yml:

    include: included.yml
    
    useTemplate:
      image: alpine
      extends: .template
    

세부 정보 병합

extends를 사용하여 해시를 병합할 수 있지만 배열은 병합할 수 없습니다. 병합에 사용되는 알고리즘은 “가장 가까운 범위가 승리”입니다. 중복 키가 있는 경우 GitLab은 키를 기반으로 역방향으로 깊은 병합을 수행합니다. 마지막 멤버에서 정의된 것은 항상 다른 수준에서 정의된 것을 재정의합니다. 예를 들어:

.only-important:
  variables:
    URL: "http://my-url.internal"
    IMPORTANT_VAR: "the details"
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    - if: $CI_COMMIT_BRANCH == "stable"
  tags:
    - production
  script:
    - echo "Hello world!"

.in-docker:
  variables:
    URL: "http://docker-url.internal"
  tags:
    - docker
  image: alpine

rspec:
  variables:
    GITLAB: "is-awesome"
  extends:
    - .only-important
    - .in-docker
  script:
    - rake rspec

결과는 다음과 같은 rspec 작업입니다:

rspec:
  variables:
    URL: "http://docker-url.internal"
    IMPORTANT_VAR: "the details"
    GITLAB: "is-awesome"
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    - if: $CI_COMMIT_BRANCH == "stable"
  tags:
    - docker
  image: alpine
  script:
    - rake rspec

이 예에서 variables 섹션이 병합되지만 URL: "http://docker-url.internal"URL: "http://my-url.internal"을 덮어쓰고 있습니다. tags: ['docker']tags: ['production']을 덮어씁니다. script는 병합되지 않지만 script: ['rake rspec']script: ['echo "Hello world!"']을 덮어쓰게 됩니다. 배열 병합에는 YAML 앵커를 사용할 수 있습니다.

!reference 태그

현재 섹션에서 다른 작업 섹션에서 키워드 구성을 선택하고 재사용하려면 사용자 정의 YAML !reference 태그를 사용하세요. YAML 앵커와는 달리 !reference 태그를 사용하여 포함된 구성 파일에서 구성을 재사용할 수 있습니다.

다음 예에서 두 개의 다른 위치에서 scriptafter_scripttest 작업에서 재사용됩니다.

  • configs.yml:

    .setup:
      script:
        - echo creating environment
    
  • .gitlab-ci.yml:

    include:
      - local: configs.yml
    
    .teardown:
      after_script:
        - echo deleting environment
    
    test:
      script:
        - !reference [.setup, script]
        - echo running my own command
      after_script:
        - !reference [.teardown, after_script]
    

다음 예에서 test-vars-1.vars의 모든 변수를 재사용하고, test-vars-2는 특정 변수를 선택하여 새 MY_VAR 변수로 재사용합니다.

.vars:
  variables:
    URL: "http://my-url.internal"
    IMPORTANT_VAR: "the details"

test-vars-1:
  variables: !reference [.vars, variables]
  script:
    - printenv

test-vars-2:
  variables:
    MY_VAR: !reference [.vars, variables, IMPORTANT_VAR]
  script:
    - printenv

parallel:matrix 키워드!reference 태그를 사용할 때 알려진 문제가 있습니다.

script, before_script, 및 after_script에서 !reference 태그 중첩

  • GitLab 16.9에서 stages 키워드에 대한 !reference 지원이 도입되었습니다.

script, before_script, 및 after_script 섹션에서 !reference 태그를 최대 10단계까지 중첩할 수 있습니다. 보다 복잡한 스크립트를 작성할 때 재사용 가능한 섹션을 정의하는 데 중첩 태그를 사용하세요. 예를 들어:

.snippets:
  one:
    - echo "ONE!"
  two:
    - !reference [.snippets, one]
    - echo "TWO!"
  three:
    - !reference [.snippets, two]
    - echo "THREE!"

nested-references:
  script:
    - !reference [.snippets, three]

이 예에서 nested-references 작업은 모든 세 개의 echo 명령을 실행합니다.

!reference 태그 지원 IDE 설정

파이프라인 에디터!reference 태그를 지원합니다. 그러나 !reference와 같은 사용자 정의 YAML 태그의 스키마 규칙이 기본적으로 편집기에서 잘못 처리될 수 있습니다. 일부 편집기에서 !reference 태그를 허용하도록 설정할 수 있습니다. 예를 들어:

  • VS Code에서 settings.json 파일에서 vscode-yaml을 파싱하여 customTags를 설정할 수 있습니다.

    "yaml.customTags": [
       "!reference sequence"
    ]
    
  • Sublime Text의 경우 LSP-yaml 패키지를 사용하고 있다면 LSP-yaml 사용자 설정에서 customTags를 설정할 수 있습니다.

    {
      "settings": {
        "yaml.customTags": ["!reference sequence"]
      }
    }
    

    ```