작업 실행 조건 지정하기 rules
rules
를 사용하여 파이프라인에서 작업을 포함하거나 제외할 수 있습니다.
규칙은 첫 번째 일치 항목을 찾을 때까지 순서대로 평가됩니다. 일치하는 항목이 발견되면 해당 작업이 구성에 따라 파이프라인에 포함되거나 제외됩니다.
작업 스크립트에서 생성된 dotenv 변수를 규칙에서 사용할 수 없습니다. 규칙은 어떤 작업이 실행되기 전에 평가되기 때문입니다.
미래의 키워드 개선에 대한 논의가 진행 중입니다. 규칙 개선을 위한 에픽에서 누구나 제안이나 요청을 추가할 수 있습니다.
rules
예제
다음 예제는 if
를 사용하여 작업이 두 가지 특정 경우에만 실행되도록 정의합니다:
job:
script: echo "Hello, Rules!"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: manual
allow_failure: true
- if: $CI_PIPELINE_SOURCE == "schedule"
- 파이프라인이 병합 요청을 위한 것이라면 첫 번째 규칙이 일치하고 작업이 병합 요청 파이프라인에 추가됩니다.
-
when: manual
(수동 작업) -
allow_failure: true
(수동 작업이 실행되지 않더라도 파이프라인은 계속 실행됨)
-
- 파이프라인이 병합 요청이 아닌 경우, 첫 번째 규칙이 일치하지 않고 두 번째 규칙이 평가됩니다.
- 파이프라인이 예약된 파이프라인인 경우 두 번째 규칙이 일치하고 작업이 예약 파이프라인에 추가됩니다. 정의된 속성이 없으므로 다음과 같이 추가됩니다:
-
when: on_success
(기본값) -
allow_failure: false
(기본값)
-
- 모든 다른 경우에 대해 규칙이 일치하지 않으므로 작업이 다른 파이프라인에 추가되지 않습니다.
다른 경우의 작업을 제외하는 규칙 세트를 정의할 수도 있지만, 모든 다른 경우에 실행되도록 할 수 있습니다:
job:
script: echo "Hello, Rules!"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: never
- if: $CI_PIPELINE_SOURCE == "schedule"
when: never
- when: on_success
- 파이프라인이 병합 요청을 위한 것이라면 작업이 파이프라인에 추가되지 않습니다.
- 파이프라인이 예약된 파이프라인인 경우 작업이 파이프라인에 추가되지 않습니다.
-
모든 다른 경우에 대해 작업이 파이프라인에 추가되며
when: on_success
로 설정됩니다.
when
절을 최종 규칙으로 사용하면 (when: never
를 포함하지 않는 경우) 동시에 두 개의 파이프라인이 시작될 수 있습니다. 푸시 파이프라인과 병합 요청 파이프라인은 동일한 이벤트(열린 병합 요청의 소스 브랜치에 대한 푸시)에 의해 트리거될 수 있습니다. 중복 파이프라인 방지 방법을 참조하십시오.예약된 파이프라인의 작업 실행
작업을 파이프라인이 예약되었을 때만 실행되도록 구성할 수 있습니다. 예를 들어:
job:on-schedule:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
script:
- make world
job:
rules:
- if: $CI_PIPELINE_SOURCE == "push"
script:
- make build
이 예제에서 make world
는 예약된 파이프라인에서 실행되고, make build
는 브랜치 및 태그 파이프라인에서 실행됩니다.
브랜치가 비어 있으면 작업 건너뛰기
브랜치가 비어 있을 때 작업을 건너뛰기 위해 rules:changes:compare_to
를 사용하여 CI/CD 리소스를 절약하십시오. 이 구성은 브랜치를 기본 브랜치와 비교하며, 브랜치가 다음과 같을 경우:
- 변경된 파일이 없으면 작업이 실행되지 않습니다.
- 변경된 파일이 있으면 작업이 실행됩니다.
예를 들어, main
이 기본 브랜치인 프로젝트에서:
job:
script:
- echo "이 작업은 비어 있지 않은 브랜치에서만 실행됩니다."
rules:
- if: $CI_COMMIT_BRANCH
changes:
compare_to: 'refs/heads/main'
paths:
- '**/*'
이 작업에 대한 규칙은 현재 브랜치의 모든 파일과 경로를 재귀적으로(**/*
) main
브랜치와 비교합니다. 이 규칙은 일치하고 브랜치의 파일에 변경 사항이 있을 때만 작업이 실행됩니다.
미리 정의된 변수와 일반 if
절
rules:if
절은 일반적으로 미리 정의된 CI/CD 변수와 함께 사용되며, 특히 CI_PIPELINE_SOURCE
미리 정의된 변수와 함께 사용됩니다.
다음 예제는 스케줄 파이프라인이나 푸시 파이프라인(브랜치 또는 태그)에 수동 작업으로 작업을 실행하며, when: on_success
(기본값)과 함께 사용됩니다. 다른 파이프라인 유형에 작업을 추가하지 않습니다.
job:
script: echo "안녕하세요, 규칙!"
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
when: manual
allow_failure: true
- if: $CI_PIPELINE_SOURCE == "push"
다음 예제는 병합 요청 파이프라인 및 스케줄 파이프라인에서 when: on_success
작업으로 작업을 실행합니다. 다른 모든 파이프라인 유형에서는 실행되지 않습니다.
job:
script: echo "안녕하세요, 규칙!"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_PIPELINE_SOURCE == "schedule"
다른 일반적으로 사용되는 if
절:
-
if: $CI_COMMIT_TAG
: 태그에 변경 사항이 푸시된 경우. -
if: $CI_COMMIT_BRANCH
: 모든 브랜치에 변경 사항이 푸시된 경우. -
if: $CI_COMMIT_BRANCH == "main"
:main
에 변경 사항이 푸시된 경우. -
if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
: 기본 브랜치에 변경 사항이 푸시된 경우. 서로 다른 기본 브랜치를 가진 여러 프로젝트에서 동일한 구성을 원할 때 사용합니다. -
if: $CI_COMMIT_BRANCH =~ /regex-expression/
: 커밋 브랜치가 정규 표현식과 일치하는 경우. -
if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_COMMIT_TITLE =~ /Merge branch.*/
: 커밋 브랜치가 기본 브랜치이고 커밋 메시지 제목이 정규 표현식과 일치하는 경우. 예를 들어, 병합 커밋의 기본 커밋 메시지는Merge branch
로 시작합니다. -
if: $CUSTOM_VARIABLE == "value1"
: 사용자 정의 변수CUSTOM_VARIABLE
이 정확히value1
인 경우.
특정 파이프라인 유형에서만 작업 실행
rules
와 함께 미리 정의된 CI/CD 변수를 사용하여 작업이 실행될 파이프라인 유형을 선택할 수 있습니다.
다음 표는 사용할 수 있는 변수와 변수가 제어할 수 있는 파이프라인 유형을 나열합니다:
- 브랜치: Git
push
이벤트에 대해 브랜치에서 실행되는 파이프라인, 새로운 커밋이나 태그와 같은. - 태그: 브랜치에 새 Git 태그가 푸시될 때만 실행되는 파이프라인.
- 병합 요청 파이프라인: 병합 요청에 대한 변경 사항에 대해 실행되는 파이프라인, 새로운 커밋이나 병합 요청의 파이프라인 탭에서 Run pipeline을 선택하는 경우와 같음.
- 스케줄 파이프라인.
변수 | 브랜치 | 태그 | 병합 요청 | 스케줄 |
---|---|---|---|---|
CI_COMMIT_BRANCH |
예 | 예 | ||
CI_COMMIT_TAG |
예 | 예, 스케줄 파이프라인이 태그에서 실행되도록 구성된 경우. | ||
CI_PIPELINE_SOURCE = push |
예 | 예 | ||
CI_PIPELINE_SOURCE = schedule |
예 | |||
CI_PIPELINE_SOURCE = merge_request_event |
예 | |||
CI_MERGE_REQUEST_IID |
예 |
예를 들어, 병합 요청 파이프라인과 스케줄 파이프라인에서만 작업을 실행하고 브랜치 또는 태그 파이프라인에서는 실행하지 않도록 작업을 구성하려면:
job1:
script:
- echo
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_PIPELINE_SOURCE == "schedule"
- if: $CI_PIPELINE_SOURCE == "push"
when: never
CI_PIPELINE_SOURCE
미리 정의된 변수
CI_PIPELINE_SOURCE
변수를 사용하여 다음 파이프라인 유형에 대해 작업을 추가할 시기를 제어합니다:
값 | 설명 |
---|---|
api |
파이프라인 API에 의해 트리거된 파이프라인을 위한 것입니다. |
chat |
GitLab ChatOps 명령어를 사용하여 생성된 파이프라인을 위한 것입니다. |
external |
GitLab 외의 CI 서비스를 사용할 때입니다. |
external_pull_request_event |
GitHub에서의 외부 풀 리퀘스트가 생성되거나 업데이트될 때입니다. |
merge_request_event |
머지 요청이 생성되거나 업데이트될 때 생성된 파이프라인을 위한 것입니다. 머지 요청 파이프라인, 머지 결과 파이프라인, 및 머지 기차를 활성화하는 데 필요합니다. |
ondemand_dast_scan |
DAST 온디맨드 스캔 파이프라인을 위한 것입니다. |
ondemand_dast_validation |
DAST 온디맨드 검증 파이프라인을 위한 것입니다. |
parent_pipeline |
부모/자식 파이프라인에 의해 트리거되는 파이프라인을 위한 것입니다. 이 파이프라인 소스를 자식 파이프라인 구성에서 사용하여 부모 파이프라인에 의해 트리거될 수 있도록 합니다. |
pipeline |
API를 사용하여 생성된 다중 프로젝트 파이프라인 또는 trigger 키워드를 위한 것입니다. |
push |
Git 푸시 이벤트에 의해 트리거된 파이프라인을 위한 것입니다. 여기에는 브랜치 및 태그가 포함됩니다. |
schedule |
예약된 파이프라인을 위한 것입니다. |
security_orchestration_policy |
보안 오케스트레이션 정책 파이프라인을 위한 것입니다. |
trigger |
트리거 토큰을 사용하여 생성된 파이프라인을 위한 것입니다. |
web |
GitLab UI의 프로젝트 Build > Pipelines 섹션에서 새 파이프라인을 선택하여 생성된 파이프라인을 위한 것입니다. |
webide |
WebIDE를 사용하여 생성된 파이프라인을 위한 것입니다. |
이 값들은 파이프라인 API 엔드포인트를 사용할 때 source
매개변수에 대해 반환되는 값과 동일합니다.
복잡한 규칙
모든 rules
키워드, 즉 if
, changes
, 및 exists
를 같은 규칙에서 사용할 수 있습니다. 규칙은 포함된 모든 키워드가 true로 평가될 때만 true로 평가됩니다.
예를 들어:
docker build:
script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
rules:
- if: $VAR == "string value"
changes: # 다음 경로 중 수정된 파일과 일치하는 경우, 작업을 포함하고 when:manual로 설정합니다.
- Dockerfile
- docker/scripts/**/*
when: manual
allow_failure: true
Dockerfile
파일 또는 /docker/scripts
내의 어떤 파일이라도 변경되었고 그리고 $VAR
== “string value”인 경우, 작업은 수동으로 실행되며 실패할 수 있습니다.
더 복잡한 변수 표현식을 구축하기 위해 괄호를 &&
및 ||
와 함께 사용할 수 있습니다.
job1:
script:
- echo 이 규칙은 괄호를 사용합니다.
rules:
- if: ($CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH == "develop") && $MY_VARIABLE
중복 파이프라인 방지
작업에 rules
를 사용하는 경우, 커밋을 브랜치에 푸시하는 것과 같은 단일 작업이 여러 파이프라인을 트리거할 수 있습니다. 여러 유형의 파이프라인을 우연히 트리거하기 위해 별도로 규칙을 구성할 필요는 없습니다.
중복 파이프라인을 유발할 가능성이 있는 구성은 파이프라인 경고를 표시하게 됩니다.
예를 들어:
job:
script: echo "이 작업은 중복 파이프라인을 생성합니다!"
rules:
- if: $CUSTOM_VARIABLE == "false"
when: never
- when: always
이 작업은 $CUSTOM_VARIABLE
이 false일 때 실행되지 않지만, 모든 다른 파이프라인에서는 실행됩니다. 여기에는 푸시(브랜치) 및 병합 요청 파이프라인 둘 다 포함됩니다. 이 구성을 사용하면, 열린 병합 요청의 소스 브랜치에 대한 모든 푸시가 중복 파이프라인을 유발합니다.
중복 파이프라인을 피하려면 다음을 수행할 수 있습니다:
-
workflow
를 사용하여 어떤 유형의 파이프라인이 실행될 수 있는지 지정합니다. -
작업이 매우 특정한 경우에만 실행되도록 규칙을 재작성하고, 최종
when
규칙을 피합니다:job: script: echo "이 작업은 중복 파이프라인을 생성하지 않습니다!" rules: - if: $CUSTOM_VARIABLE == "true" && $CI_PIPELINE_SOURCE == "merge_request_event"
또한, 작업 규칙을 변경하여 푸시(브랜치) 파이프라인 또는 병합 요청 파이프라인을 피함으로써 중복 파이프라인을 방지할 수 있습니다. 그러나 - when: always
규칙을 workflow: rules
없이 사용하는 경우 GitLab은 여전히 파이프라인 경고를 표시합니다.
예를 들어, 다음은 중복 파이프라인을 트리거하지 않지만 workflow: rules
없이 사용하는 것은 권장되지 않습니다:
job:
script: echo "이 작업은 중복 파이프라인을 생성하지 않습니다!"
rules:
- if: $CI_PIPELINE_SOURCE == "push"
when: never
- when: always
push
및 병합 요청 파이프라인을 동일한 작업에 포함해서는 안 됩니다 workflow:rules
가 중복 파이프라인을 방지합니다:
job:
script: echo "이 작업은 중복 파이프라인을 생성합니다!"
rules:
- if: $CI_PIPELINE_SOURCE == "push"
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
또한 only/except
작업과 rules
작업을 동일한 파이프라인에 혼합하지 마십시오. YAML 오류를 유발하지는 않지만 only/except
와 rules
의 기본 동작이 다르기 때문에 문제를 해결하기 어려운 문제를 초래할 수 있습니다:
job-with-no-rules:
script: echo "이 작업은 브랜치 파이프라인에서 실행됩니다."
job-with-rules:
script: echo "이 작업은 병합 요청 파이프라인에서 실행됩니다."
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
브랜치에 푸시되는 모든 변경에 대해 중복 파이프라인이 실행됩니다. 하나의 브랜치 파이프라인이 단일 작업(job-with-no-rules
)을 실행하고, 하나의 병합 요청 파이프라인이 다른 작업(job-with-rules
)을 실행합니다. 규칙이 없는 작업은 기본적으로 except: merge_requests
로 설정되므로 job-with-no-rules
는 병합 요청을 제외한 모든 경우에 실행됩니다.
다양한 작업에서 규칙 재사용
다양한 작업에서 규칙을 재사용하려면 !reference
태그를 사용하십시오. !reference
규칙을 일반 작업 정의 규칙과 결합할 수 있습니다. 예를 들어:
.default_rules:
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
when: never
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
job1:
rules:
- !reference [.default_rules, rules]
script:
- echo "이 작업은 기본 브랜치에 대해 실행되지만, 스케줄에는 실행되지 않습니다."
job2:
rules:
- !reference [.default_rules, rules]
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- echo "이 작업은 기본 브랜치에 대해 실행되지만, 스케줄에는 실행되지 않습니다."
- echo "병합 요청에 대해서도 실행됩니다."
CI/CD 변수 표현식
rules:if
을 사용하여 변수 표현식으로
작업이 언제 파이프라인에 추가되어야 하는지를 제어할 수 있습니다.
문자열과 변수를 비교하기 위해 ==
및 !=
같음 연산자를 사용할 수 있습니다.
단일 따옴표와 이중 따옴표 모두 유효합니다. 비교의 왼쪽에는 변수가 있어야 합니다. 예를 들어:
if: $VARIABLE == "some value"
if: $VARIABLE != "some value"
두 변수의 값을 비교할 수 있습니다. 예를 들어:
if: $VARIABLE_1 == $VARIABLE_2
if: $VARIABLE_1 != $VARIABLE_2
변수가 정의되었는지를 확인하기 위해 null
키워드와 비교할 수 있습니다. 예를 들어:
if: $VARIABLE == null
if: $VARIABLE != null
변수가 정의되어 있지만 비어 있는지를 확인할 수 있습니다. 예를 들어:
if: $VARIABLE == ""
if: $VARIABLE != ""
변수가 정의되어 있고 비어 있지 않음을 확인하려면 표현식에서 변수 이름만 사용하면 됩니다. 예를 들어:
if: $VARIABLE
변수를 정규 표현식과 비교
변수 값에 대해 =~
및 !~
연산자를 사용하여 정규 표현식 일치를 수행할 수 있습니다.
정규 표현식으로 변수를 패턴 매칭하는 것은 RE2 정규 표현식 구문을 사용합니다.
표현식은 다음과 같이 평가됩니다 true
:
-
=~
를 사용할 때 일치 항목이 발견됩니다. -
!~
를 사용할 때 일치 항목이 발견되지 않습니다.
예를 들어:
if: $VARIABLE =~ /^content.*/
if: $VARIABLE !~ /^content.*/
추가적으로:
-
/./
와 같은 단일 문자 정규 표현식은 지원되지 않으며invalid expression syntax
오류가 발생합니다. - 패턴 매칭은 기본적으로 대소문자를 구분합니다. 패턴이 대소문자를 구분하지 않도록 만들려면
i
플래그 수식어를 사용합니다. 예:/pattern/i
. - 정규 표현식으로 일치할 수 있는 것은 태그 또는 브랜치 이름뿐입니다. 제공된 경우 저장소 경로는 항상 리터럴하게 일치합니다.
- 전체 패턴은
/
로 둘러싸여야 합니다. 예를 들어issue-/.*/
을 사용하여issue-
로 시작하는 모든 태그 이름이나 브랜치 이름과 일치시킬 수 없지만/issue-.*/
를 사용할 수 있습니다. -
@
기호는 참조의 저장소 경로의 시작을 나타냅니다. 정규 표현식에서@
문자가 포함된 참조 이름과 일치시키려면 16진수 문자 코드 일치\x40
을 사용해야 합니다. - 태그 이름이나 브랜치 이름의 부분 문자열만 일치하지 않도록
^
및$
앵커를 사용합니다. 예를 들어/^issue-.*$/
는/^issue-/
와 동일하며, 단순히/issue/
는severe-issues
라는 브랜치도 일치합니다.
정규 표현식을 변수에 저장하기
- GitLab 15.0에서 도입됨 플래그와 함께
ci_fix_rules_if_comparison_with_regexp_variable
, 기본적으로 비활성화됨.- 일반적으로 사용 가능하며 기능 플래그
ci_fix_rules_if_comparison_with_regexp_variable
는 GitLab 15.1에서 제거됨.
=~
및 !~
표현식의 오른쪽에 있는 변수는 정규 표현식으로 평가됩니다.
정규 표현식은 슬래시(/
)로 감싸야 합니다. 예를 들어:
variables:
pattern: '/^ab.*/'
regex-job1:
variables:
teststring: 'abcde'
script: echo "이 작업은 'abcde'가 /^ab.*/ 패턴과 일치하므로 실행됩니다."
rules:
- if: '$teststring =~ $pattern'
regex-job2:
variables:
teststring: 'fghij'
script: echo "이 작업은 'fghi'가 /^ab.*/ 패턴과 일치하지 않으므로 실행되지 않습니다."
rules:
- if: '$teststring =~ $pattern'
정규 표현식의 변수는 해결되지 않습니다. 예를 들어:
variables:
string1: 'regex-job1'
string2: 'regex-job2'
pattern: '/$string2/'
regex-job1:
script: echo "이 작업은 실행되지 않습니다. 왜냐하면 정규 표현식 패턴 내부의 'string1' 변수가 해결되지 않기 때문입니다."
rules:
- if: '$CI_JOB_NAME =~ /$string1/'
regex-job2:
script: echo "이 작업은 실행되지 않습니다. 왜냐하면 'pattern' 변수 내부의 'string2' 변수가 해결되지 않기 때문입니다."
rules:
- if: '$CI_JOB_NAME =~ $pattern'
변수 표현식 결합
여러 표현식을 &&
(그리고) 또는 ||
(또는)를 사용하여 결합할 수 있습니다. 예를 들어:
$VARIABLE1 =~ /^content.*/ && $VARIABLE2 == "something"
$VARIABLE1 =~ /^content.*/ && $VARIABLE2 =~ /thing$/ && $VARIABLE3
$VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/ && $VARIABLE3
연산자의 우선순위는 Ruby 2.5 표준을 따르므로, &&
는 ||
보다 먼저 평가됩니다.
괄호를 사용하여 표현식을 그룹화할 수 있습니다. 괄호는 &&
와 ||
보다 우선 순위를 가지므로, 괄호로 묶인 표현식이 먼저 평가되고, 그 결과가 나머지 표현식에 사용됩니다.
복잡한 조건을 만들기 위해 괄호를 중첩하여 사용하고, 괄호 안의 가장 안쪽 표현식이 먼저 평가됩니다. 예를 들어:
($VARIABLE1 =~ /^content.*/ || $VARIABLE2) && ($VARIABLE3 =~ /thing$/ || $VARIABLE4)
($VARIABLE1 =~ /^content.*/ || $VARIABLE2 =~ /thing$/) && $VARIABLE3
$CI_COMMIT_BRANCH == "my-branch" || (($VARIABLE1 == "thing" || $VARIABLE2 == "thing") && $VARIABLE3)
문제 해결
=~
를 사용한 정규 표현식 매칭의 예기치 않은 동작
=~
기호를 사용할 때, 비교의 오른쪽에는 항상 유효한 정규 표현식이 포함되어야 합니다.
비교의 오른쪽이 /
문자로 감싸인 유효한 정규 표현식이 아니면, 표현식이 예기치 않게 평가됩니다. 이 경우, 비교는 왼쪽이 오른쪽의 부분 문자열인지 확인합니다. 예를 들어, "23" =~ "1234"
는 참으로 평가되며, 이는 "23" =~ /1234/
와는 반대로, 후자는 거짓으로 평가됩니다.
이 동작에 의존하도록 파이프라인을 구성해서는 안 됩니다.