job 실행 제어하기

job 실행 제어하기 (Control how jobs run)

새 파이프라인이 시작되기 전에 GitLab은 파이프라인 구성을 확인해서 어떤 job이 실행될 수 있는지 결정해요. 변수 값이나 파이프라인 유형 같은 조건에 따라 job을 실행하도록 rules로 구성할 수 있습니다. job 규칙을 쓸 때는 중복 파이프라인을 피하는 방법을 배워 두세요. 파이프라인 생성을 제어하려면 workflow:rules를 사용하세요.

출처: 문서

본문

  • 티어(Tier): Free, Premium, Ultimate
  • 제공 방식(Offering): GitLab.com, GitLab Self-Managed, GitLab Dedicated

수동으로 실행해야 하는 job 만들기

사용자가 시작하지 않으면 실행되지 않는 job을 만들 수 있어요. 이런 job을 **수동 job(manual job)**이라고 해요. 프로덕션에 배포하는 것 같은 작업에 수동 job을 쓰기 좋습니다.

job을 수동으로 지정하려면 .gitlab-ci.yml 파일의 job에 when: manual을 추가하세요.

기본적으로 수동 job은 파이프라인이 시작될 때 건너뛴 것으로(skipped) 표시돼요.

보호된 브랜치를 사용하면 미승인 사용자가 수동 배포를 실행하지 못하도록 더 엄격하게 보호할 수 있어요.

아카이브된 수동 job은 실행되지 않아요.

수동 job의 유형

수동 job은 선택 사항(optional) 또는 차단(blocking)일 수 있어요.

선택 사항 수동 job에서:

  • allow_failuretrue예요. rules 밖에서 when: manual이 정의된 job의 기본 설정이에요.
  • 이 상태는 전체 파이프라인 상태에 기여하지 않아요. 모든 수동 job이 실패해도 파이프라인은 성공할 수 있어요.

차단 수동 job에서:

  • allow_failurefalse예요. rules 안에서 when: manual이 정의된 job의 기본 설정이에요.
  • 파이프라인은 job이 정의된 스테이지에서 멈춰요. 파이프라인을 계속 실행하려면 수동 job을 실행하세요.
  • Pipelines must succeed가 활성화된 프로젝트의 MR은 차단된 파이프라인으로는 머지할 수 없어요.
  • 파이프라인은 blocked 상태를 보여줘요.

trigger:strategy로 다운스트림 파이프라인에서 수동 job을 쓸 때, 수동 job의 유형은 파이프라인이 실행되는 동안 트리거 job의 상태에 영향을 줄 수 있어요.

수동 job 실행하기

수동 job을 실행하려면 할당된 브랜치에 머지할 권한이 있어야 해요:

  1. 파이프라인, job, 환경, 또는 배포 보기로 이동해요.
  2. 수동 job 옆에서 Run(play)을 선택해요.

수동 job 실행 시 변수 지정하기

수동 job을 실행할 때 job별 추가 CI/CD 변수를 제공할 수 있어요. CI/CD 변수를 사용하는 job의 실행을 바꾸고 싶을 때 여기서 변수를 지정하세요.

수동 job을 실행하고 재시도할 때 모두 재정의할 수 있는 타입이 지정된 검증 파라미터를 원한다면 job inputs를 대신 사용하세요.

수동 job을 실행하고 추가 변수를 지정하려면:

  • 파이프라인 뷰에서 Run(play)이 아니라 수동 job의 name을 선택해요.
  • 양식에서 변수 키와 값 쌍을 추가해요.
  • Run job을 선택해요.

수동 job을 실행할 권한이 있는 모든 프로젝트 멤버는 job을 재시도하고 처음 실행될 때 제공된 변수를 볼 수 있어요. 여기에는:

  • 공개 프로젝트: Developer, Maintainer, Owner 역할의 사용자.
  • 프라이빗 또는 내부 프로젝트: Guest, Planner, Reporter, Developer, Maintainer, Owner 역할의 사용자.

수동 job 변수에 민감한 정보를 입력할 때는 이 가시성을 고려하세요.

CI/CD 설정이나 .gitlab-ci.yml 파일에 이미 정의된 변수를 추가하면 변수가 새 값으로 재정의돼요. 이 과정으로 재정의된 변수는 확장되고 마스킹되지 않습니다.

업데이트된 변수로 수동 job 재시도하기

이전에 수동으로 지정한 변수로 실행된 수동 job을 재시도할 때, 변수를 업데이트하거나 같은 변수를 사용할 수 있어요.

타입이 지정된 검증 파라미터로 수동 job을 재시도하려면 job inputs를 대신 사용하세요.

이전에 지정된 변수로 수동 job을 재시도하는 방법:

  • 같은 변수 사용: - job 세부 정보 페이지에서 Retry(retry)를 선택해요.
  • 업데이트된 변수 사용: - job 세부 정보 페이지의 드롭다운 목록에서 Retry job with modified values를 선택해요. - 이전 실행에서 지정된 변수가 양식에 미리 채워져 있어요. 이 양식에서 CI/CD 변수를 추가, 수정, 삭제할 수 있어요. - Run job again을 선택해요.

수동 job에 확인 요구하기

수동 job에 확인을 요구하려면 when: manual과 함께 manual_confirmation을 사용하세요. 이는 프로덕션에 배포하는 작업 같은 민감한 job에서 실수로 배포되거나 삭제되는 것을 막는 데 도움을 줘요.

job을 실행하면 실행되기 전에 작업을 확인해야 합니다.

수동 job 보호하기

  • 티어(Tier): Premium, Ultimate
  • 제공 방식(Offering): GitLab.com, GitLab Self-Managed, GitLab Dedicated

보호된 환경을 사용해 수동 job을 실행할 권한이 있는 사용자 목록을 정의하세요. 보호된 환경과 연결된 사용자만 수동 job을 실행하도록 승인할 수 있어요. 이렇게 하면:

  • 환경에 배포할 수 있는 사람을 더 정밀하게 제한할 수 있어요.
  • 승인된 사용자가 "승인"할 때까지 파이프라인을 차단할 수 있어요.

수동 job을 보호하려면:

  1. job에 environment를 추가해요. 예를 들어: deploy_prod: stage: deploy script: - echo "Deploy to production server" environment: name: production url: https://example.com when: manual rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  2. 보호된 환경 설정에서 환경(이 예시에서는 production)을 선택하고, 수동 job을 실행할 권한이 있는 사용자·역할·그룹을 Allowed to Deploy 목록에 추가해요. 이 목록의 사용자나 GitLab 관리자만 이 수동 job을 실행할 수 있어요.

보호된 환경을 차단 수동 job과 함께 사용하면, 이후 파이프라인 스테이지를 승인할 수 있는 사용자 목록을 가질 수 있어요. 보호된 수동 job에 allow_failure: false를 추가하면 파이프라인의 다음 스테이지들이 권한 있는 사용자가 수동 job을 트리거한 뒤에만 실행됩니다.

지연 후 job 실행하기

대기 시간 후 스크립트를 실행하거나, job이 pending 상태로 즉시 진입하는 것을 피하고 싶을 때 when: delayed를 사용해요.

기간은 start_in 키워드로 설정할 수 있어요. start_in 값은 단위가 제공되지 않으면 경과 시간(초)이에요. 최소 1초, 최대 1주일입니다. 유효한 값의 예는 다음과 같아요:

  • '5' (단위가 없는 값은 작은따옴표로 감싸야 해요)
  • 5 seconds
  • 30 minutes
  • 1 day
  • 1 week

스테이지에 지연 job이 포함되면, 지연 job이 끝날 때까지 파이프라인은 진행되지 않아요. 이 키워드로 서로 다른 스테이지 사이에 지연을 넣을 수 있습니다.

지연 job의 타이머는 이전 스테이지가 완료된 직후 시작돼요. 다른 job 유형과 마찬가지로, 지연 job의 타이머는 이전 스테이지가 통과하지 않으면 시작되지 않습니다.

다음 예시는 이전 스테이지 완료 30분 후에 실행되는 timed rollout 10%라는 job을 만듭니다:

timed rollout 10%:
  stage: deploy
  script: echo 'Rolling out 10% ...'
  when: delayed
  start_in: 30 minutes
  environment: production

지연 job의 활성 타이머를 멈추려면 Unschedule(time-out)을 선택해요. 이 job은 더 이상 자동으로 실행되도록 예약할 수 없지만, 수동으로는 실행할 수 있어요.

지연 job을 수동으로 시작하려면 Unschedule(time-out)로 지연 타이머를 멈춘 다음 Run(play)을 선택하세요. 곧 GitLab Runner가 job을 시작합니다.

아카이브된 지연 job은 실행되지 않아요.

큰 job 병렬화하기

큰 job을 병렬로 실행되는 여러 작은 job으로 나누려면 .gitlab-ci.yml 파일에서 parallel 키워드를 사용하세요.

언어와 테스트 스위트마다 병렬화를 활성화하는 방법이 달라요. 예를 들어 Semaphore Test Boosters와 RSpec으로 Ruby 테스트를 병렬 실행할 수 있어요:

# Gemfile
source 'https://rubygems.org'

gem 'rspec'
gem 'semaphore_test_boosters'
test:
  parallel: 3
  script:
    - bundle
    - bundle exec rspec_booster --job $CI_NODE_INDEX/$CI_NODE_TOTAL

그런 다음 새 파이프라인 빌드의 Jobs 탭으로 가면 RSpec job이 세 개의 별도 job으로 나뉜 것을 볼 수 있어요.

Test Boosters는 작성자에게 사용 통계를 보고해요.

1차원 병렬 job 매트릭스 실행하기

단일 파이프라인에서 job을 여러 번 병렬로 실행하되, job 인스턴스마다 다른 값을 사용하려면 parallel:matrix 키워드를 사용해요:

deploystacks:
  stage: deploy
  script:
    - bin/deploy
  parallel:
    matrix:
      - PROVIDER: [aws, ovh, gcp, vultr]
  environment: production/$PROVIDER

이 예시에서는 4개의 deploystacks job이 만들어지고, PROVIDER가 각 job마다 다른 값을 가진 CI/CD 변수가 됩니다:

  • deploystacks: [aws]
  • deploystacks: [ovh]
  • deploystacks: [gcp]
  • deploystacks: [vultr]

병렬 트리거 job 매트릭스 실행하기

트리거 job을 단일 파이프라인에서 여러 번 병렬로 실행하되, job 인스턴스마다 사용할 다른 변수를 지정할 수 있어요.

예를 들어:

deploystacks:
  stage: deploy
  trigger:
    include: path/to/child-pipeline.yml
  parallel:
    matrix:
      - PROVIDER: aws
        STACK: [monitoring, app1]
      - PROVIDER: ovh
        STACK: [monitoring, backup]
      - PROVIDER: [gcp, vultr]
        STACK: [data]

이 예시는 PROVIDERSTACK에 서로 다른 값을 가진 6개의 병렬 deploystacks 트리거 job을 생성하고, 그 변수들로 6개의 서로 다른 자식 파이프라인을 만듭니다.

deploystacks: [aws, monitoring]
deploystacks: [aws, app1]
deploystacks: [ovh, monitoring]
deploystacks: [ovh, backup]
deploystacks: [gcp, data]
deploystacks: [vultr, data]

각 병렬 매트릭스 job에 다른 러너 태그 선택하기

parallel: matrix에 정의된 값을 tags 키워드와 함께 사용해 동적으로 러너를 선택할 수 있어요:

deploystacks:
  stage: deploy
  script:
    - bin/deploy
  parallel:
    matrix:
      - PROVIDER: aws
        STACK: [monitoring, app1]
      - PROVIDER: gcp
        STACK: [data]
  tags:
    - ${PROVIDER}-${STACK}
  environment: $PROVIDER/$STACK

rules에서 매트릭스 변수 사용하기

GitLab은 개별 매트릭스 job마다 그 job의 변수 값을 사용해 rules를 별도로 평가해요.

rules:if에서 매트릭스 변수 사용하기

rules:if 표현식에서 매트릭스 변수를 사용해 변수 값에 따라 개별 매트릭스 job을 포함하거나 제외할 수 있어요.

예를 들어 매트릭스 변수 SKIP"true"로 설정되면 job을 건너뛰려면:

test:
  script: echo "Building $ARCH"
  parallel:
    matrix:
      - ARCH: [amd64, arm64]
        SKIP: ["false", "true"]
  rules:
    - if: $SKIP == "true"
      when: never
    - when: on_success

SKIP"false"인 job만 파이프라인에 포함돼요.

rules:if의 매트릭스 변수는 중첩 확장을 지원하지 않아요. 매트릭스 변수 값이 다른 CI/CD 변수를 참조하면(예: FILE: $GLOBAL_FILE), 그 참조는 해석되지 않습니다. 표현식은 리터럴 문자열 값을 사용하므로 $FILEGLOBAL_FILE의 값이 아니라 "$GLOBAL_FILE"로 평가됩니다.

rules:changes에서 매트릭스 변수 사용하기

rules:changes 경로에서 매트릭스 변수를 사용해, 해당 job과 관련된 파일이 변경되었을 때만 매트릭스 job을 포함할 수 있어요. 각 매트릭스 값이 자신만의 디렉터리를 가진 구성 요소나 서비스에 해당하는 모노레포에서 이 패턴을 사용하세요.

예를 들어 파일이 변경된 구성 요소에 대해서만 테스트 job을 실행하려면:

test:
  script: echo "Testing $COMPONENT"
  parallel:
    matrix:
      - COMPONENT: [frontend, backend, database]
  rules:
    - if: $CI_PIPELINE_SOURCE == "push"
      changes:
        - components/$COMPONENT/**/*

이 예시에서:

  • COMPONENT 값에 대해 세 개의 test job이 평가돼요.
  • 각 job은 자체 $COMPONENT 값을 경로에 대입한 rules:changes를 확인해요.
  • 일치하는 파일이 변경된 job만 파이프라인에 추가돼요.

예를 들어 components/frontend/npm.lock만 변경됐다면 frontend job만 실행돼요.

같은 경로에서 여러 매트릭스 변수를 사용할 수 있어요:

test:
  script: echo "Testing $SERVICE in $ENV"
  parallel:
    matrix:
      - SERVICE: [api, web]
        ENV: [dev, prod]
  rules:
    - changes:
        - config/$SERVICE/$ENV/**/*

rules:exists에서 매트릭스 변수 사용하기

rules:exists 경로에서 매트릭스 변수를 사용해 특정 파일이 존재할 때만 매트릭스 job을 포함할 수 있어요.

예를 들어:

test:
  script: echo "Testing $TYPE"
  parallel:
    matrix:
      - TYPE: [go, ruby, python]
  rules:
    - exists:
        - "**/*.$TYPE"

parallel:matrix job에서 아티팩트 가져오기

parallel:matrix로 만든 job에서 아티팩트를 가져오려면 dependencies 키워드를 사용해요. dependencies 값으로 job 이름을 다음 형식의 문자열로 사용하세요:

<job_name> [<matrix argument 1>, <matrix argument 2>, ... <matrix argument N>]

예를 들어 RUBY_VERSION2.7이고 PROVIDERaws인 job에서 아티팩트를 가져오려면:

ruby:
  image: ruby:${RUBY_VERSION}
  parallel:
    matrix:
      - RUBY_VERSION: ["2.5", "2.6", "2.7", "3.0", "3.1"]
        PROVIDER: [aws, gcp]
  script: bundle install

deploy:
  image: ruby:2.7
  stage: deploy
  dependencies:
    - "ruby: [2.7, aws]"
  script: echo hello
  environment: production

dependencies 항목 주위의 따옴표는 필수예요.

needs로 여러 병렬 job 지정하기

needs:parallel:matrix를 사용해 여러 병렬 job 사이에 job 의존성을 만들 수 있어요.

구성에는 두 가지 기법을 쓸 수 있어요:

예를 들어:

linux:build:
  stage: build
  script: echo "Building linux..."
  parallel:
    matrix:
      - PROVIDER: aws
        STACK:
          - monitoring
          - app1
          - app2

mac:build:
  stage: build
  script: echo "Building mac..."
  parallel:
    matrix:
      - PROVIDER: [gcp, vultr]
        STACK: [data, processing]

linux:rspec:
  stage: test
  needs:
    - job: linux:build
      parallel:
        matrix:
          - PROVIDER: aws
            STACK: app1
  script: echo "Running rspec on linux..."

mac:rspec:
  stage: test
  needs:
    - job: mac:build
      parallel:
        matrix:
          - PROVIDER: [gcp, vultr]
            STACK: [data]
  script: echo "Running rspec on mac..."

production:
  stage: deploy
  script: echo "Running production..."
  environment: production

이 예시는 여러 job을 생성해요. 병렬 job들은 각각 PROVIDERSTACK에 서로 다른 값을 갖습니다.

  • 3개의 병렬 linux:build job: - linux:build: [aws, monitoring] - linux:build: [aws, app1] - linux:build: [aws, app2]
  • 4개의 병렬 mac:build job: - mac:build: [gcp, data] - mac:build: [gcp, processing] - mac:build: [vultr, data] - mac:build: [vultr, processing]
  • linux:rspec job.
  • production job.

job들은 세 가지 실행 경로를 가져요:

  • Linux 경로: linux:rspec job은 linux:build: [aws, app1] job이 끝나는 즉시 실행되고, mac:build가 끝나길 기다리지 않아요.
  • macOS 경로: mac:rspec job은 mac:build: [gcp, data]mac:build: [vultr, data] job이 끝나는 즉시 실행되고, linux:build가 끝나길 기다리지 않아요.
  • production job은 이전 모든 job이 끝나는 즉시 실행돼요.

병렬 job 간 needs 지정하기

needs:parallel:matrix로 각 병렬 매트릭스 job의 순서를 더 정의할 수 있어요.

예를 들어:

build_job:
  stage: build
  script:
    # ensure that other parallel job other than build_job [1, A] runs longer
    - '[[ "$VERSION" == "1" && "$MODE" == "A" ]] || sleep 30'
    - echo build $VERSION $MODE
  parallel:
    matrix:
      - VERSION: [1,2]
        MODE: [A, B]

deploy_job:
  stage: deploy
  script: echo deploy $VERSION $MODE
  parallel:
    matrix:
      - VERSION: [3,4]
        MODE: [C, D]

'deploy_job: [3, D]':
  stage: deploy
  script: echo something
  needs:
  - 'build_job: [1, A]'

이 예시는 여러 job을 생성해요. 병렬 job들은 각각 VERSIONMODE에 서로 다른 값을 갖습니다.

  • 4개의 병렬 build_job job: - build_job: [1, A] - build_job: [1, B] - build_job: [2, A] - build_job: [2, B]
  • 4개의 병렬 deploy_job job: - deploy_job: [3, C] - deploy_job: [3, D] - deploy_job: [4, C] - deploy_job: [4, D]

deploy_job: [3, D] job은 build_job: [1, A] job이 끝나는 즉시 실행되고, 다른 build_job이 끝나길 기다리지 않아요.

문제 해결 (Troubleshooting)

수동 job 실행 시 사용자 할당이 일관되지 않아요

일부 엣지 케이스에서 수동 job을 실행한 사용자가 그 수동 job에 의존하는 이후 job의 사용자로 할당되지 않을 수 있어요.

수동 job에 의존하는 job의 사용자로 누가 할당되는지에 대해 엄격한 보안이 필요하다면 수동 job을 보호해야 해요.

더 알아보기 (Learn more)