Status | Authors | Coach | DRIs | Owning Stage | Created |
---|---|---|---|---|---|
proposed |
@furkanayhan
|
@ayufan
|
@jreporter
@cheryl.li
| devops verify | 2023-05-15 |
CI 파이프라인 처리의 미래
GitLab CI는 GitLab의 가장 오래되고 복잡한 기능 중 하나입니다. 여러 해 동안 그 YAML 구문은 크게 커지고 복잡해졌습니다. 이러한 구문을 몇 년 동안 매우 안정적으로 유지하기 위해 우리는 기존 디자인과 패턴에 주로 추가적인 변경을 가해왔습니다. 우리의 사용자 기반은 지난 몇 년 동안 기하급수적으로 증가했습니다. 그로 인해 사용자의 사용 사례를 지원하고 워크플로의 사용자 정의가 필요해졌습니다.
여러 해 동안 막대한 가치를 전달했지만, 구문에 대한 여러 추가적인 변경으로 파이프라인 처리 로직에서 어떤 예상치 못한 동작을 유발하기도 했습니다. 몇 가지 키워드가 책임을 많이 짊어지고, 키워드 간 모호한 중첩과 시간이 지남에 따라 서서히 다른 동작이 도입되기도 했습니다. 현재의 구현과 YAML 구문은 새로운 기능을 구현하기 어렵게 만듭니다.
이 설계 문서에서는 파이프라인 처리에 대한 문제점을 논의하고 새로운 아키텍처를 제안할 것입니다. 이러한 문제들은 이전에 “Restructure CI job when keyword” epic에서 이미 논의되었습니다.
목표
- 파이프라인 처리를 더 이해하기 쉽고 예측 가능하며 일관성 있게 만들고자 합니다.
- DAG와 STAGE의 동작을 통합하고, STAGE는 DAG로 작성될 수 있도록 합니다.
- 매뉴얼 작업의 차단 동작을
allow_failure
키워드와 분리하고자 합니다. -
when
키워드의 책임을 명확히 하고자 합니다.
비목표
지금은 파괴적인 변화를 피하는 방법에 대해 논의하지 않을 것입니다.
동기
문제 디렉터리이 이 설계 문서의 주요 동기입니다.
문제 1: when
키워드의 책임
현재 when
키워드는 다양한 책임을 갖고 있습니다.
on_success
(기본값): 이전 단계의 작업 중 하나라도 실패하지 않았거나allow_failure: true
를 갖는 작업이 없는 경우에만 작업을 실행합니다.on_failure
: 이전 단계에서 하나 이상의 작업이 실패한 경우에만 작업을 실행합니다. 이전 단계에서allow_failure: true
를 갖는 작업은 항상 성공한 것으로 간주됩니다.never
: 이전 단계의 상태에 관계없이 작업을 실행하지 않습니다.rules
섹션이나workflow: rules
에서만 사용할 수 있습니다.always
: 이전 단계의 상태에 관계없이 작업을 실행합니다.workflow:rules
에서도 사용할 수 있습니다.manual
: 수동으로 트리거된 경우에만 작업을 실행합니다.delayed
: 지정된 기간 동안 작업을 지연시킵니다.
이것은 세 가지 질문에 대답합니다.
- 실행하기 위해 필요한 것은 무엇인가요? =>
on_success
,on_failure
,always
- 어떻게 실행하죠? =>
manual
,delayed
- 파이프라인에 추가하나요? =>
never
결과적으로, 예를 들어, on_failure
과 함께 manual
작업을 생성할 수 없습니다. 이는 사용자가 실패 시에만 사용 가능하고 매뉴얼으로 실행해야 하는 작업을 만들고자 할 때 유용할 수 있습니다. 예를 들어, 실패 사항을 전용 페이지나 전용 외부 서비스로 발행하는 경우입니다.
문제 2: allow_failure
키워드의 남용
매뉴얼 작업의 차단 동작은 현재 allow_failure
키워드로 제어합니다. 사실, 이것은 다른 책임도 있습니다; “작업이 실패할 때 파이프라인을 계속 실행할지 여부를 결정합니다”.
현재, 매뉴얼 작업;
-
allow_failure: true
일 때 차단 요소가 아닙니다 (기본값) -
allow_failure: false
일 때 차단 요소가 됩니다.
문제 4: 건너뛰고 무시된 상태
문제 3을 해결했다고 가정하고 “건너뛰기”와 “무시하기” 상태가 DAG와 STAGE에서 다르지 않다고 가정해 봅시다. 이들은 일반적으로 어떻게 동작해야 합니까? 성공적인가요 아니면 아닙니까? “건너뛰기”와 “무시하기”는 달라야합니까? 몇 가지 예를 살펴보겠습니다.
예제 4.1. 매뉴얼 작업에서 무시된 상태
build:
stage: build
script: exit 0
when: manual
allow_failure: true # 기본값
test:
stage: test
script: exit 0
-
build
는 “매뉴얼” 상태지만 파이프라인 처리에서 “건너뛰기”(무시하기)로 간주됩니다. -
test
는 “건너뛰기”가 성공적인 상태이기 때문에 실행됩니다.
또는;
build1:
stage: build
script: exit 0
when: manual
allow_failure: true # 기본값
build2:
stage: build
script: exit 0
test:
stage: test
script: exit 0
-
build1
는 “매뉴얼” 상태지만 파이프라인 처리에서 “건너뛰기”(무시하기)로 간주됩니다. -
build2
는 실행되어 성공합니다. -
test
는 “성공” + “건너뛰기”가 성공적인 상태이기 때문에 실행됩니다.
예제 4.2. 실패 시 when:를 사용한 건너뛰기 상태
build:
stage: build
script: exit 0
when: on_failure
test:
stage: test
script: exit 0
-
build
는when: on_failure
이기 때문에 이전 상태가 “실패”가 아니기 때문에 건너뛰어집니다. -
test
는 “건너뛰기”가 성공적인 상태이기 때문에 실행됩니다.
또는;
build1:
stage: build
script: exit 0
when: on_failure
build2:
stage: build
script: exit 0
test:
stage: test
script: exit 0
-
build1
는when: on_failure
이기 때문에 이전 상태가 “실패”가 아니기 때문에 건너뛰어집니다. -
build2
는 실행되어 성공합니다. -
test
는 “성공” + “건너뛰기”가 성공적인 상태이기 때문에 실행됩니다.
문제 5: dependencies
키워드
dependencies
키워드는 artifacts 디렉터리을 정의하는 데 사용됩니다. needs
키워드와 공동 책임을 지닙니다.
또한 같은 작업에서 함께 사용될 수 있습니다. 모든 가능한 시나리오를 논의할 필요는 없겠지만, 이 예제만 있으면 혼란을 보일 수 있습니다.
test2:
script: exit 0
dependencies: [test1]
needs:
- job: test1
artifacts: false
정보 1: 취소된 작업
취소된 작업과 실패한 작업은 같습니까? 많은 차이점이 있으므로 “아니오”라고 쉽게 말할 수 있습니다. 하지만 하나의 유사점이 있습니다; “실패해도 괜찮음”으로 설정할 수 있다는 것입니다.
먼저 그들의 차이점을 정의해 봅시다.
- 취소된 작업;
- 끝나지 않은 작업입니다.
- 취소된 작업은 사용자 요청에 의한 작업 중단입니다. 의도는 가능한 한 빨리 작업을 중단하거나 파이프라인 처리를 중지하는 것입니다.
- 결과를 알 수 없으며 artifact가 없습니다 등.
- 실행되지 않았기 때문에
after_script
이 실행되지 않습니다. - 최종 상태는 “취소됨”이며 그 후에는 작업을 실행할 수 없습니다.
-
when: on_canceled
가 없습니다. -
when: always
조차 실행되지 않습니다.
-
- 실패한 작업;
- CI 시스템의 기계적 응답입니다. 실행에 실패했음을 나타냅니다.
- 실패한 것은 상대적으로 곧 성공에 대한 응답과 동일합니다. 실패한 것이 무엇인지는 상황에 따라 다르며 일부는 테스트가 실패할 때와 같이 CI 실행의 원하는 결과일 수 있습니다.
- 결과를 알며 artifact가 있을 수 있습니다.
-
after_script
이 실행됩니다. - 최종 상태는 “실패”이며 후속 작업은 그들의
when
값에 따라 실행됩니다.-
when: on_failure
및when: always
가 실행됩니다.
-
유사점은 ‘실패해도 괜찮음’으로 설정될 수 있다는 것입니다.
build:
stage: build
script: sleep 10
allow_failure: true
test:
stage: test
script: exit 0
when: on_success
-
build
가 실행되어취소
되면test
가 실행됩니다. -
build
가 실행되어실패
하면test
가 실행됩니다.
일부 경우에는 실패
대신 취소
를 사용하는 아이디어
다른 측면도 있습니다. 우리는 종종 컴퓨팅 크레딧(CI 분)이 부족하거나 제한이 초과되었을 때 failure_reason
로 인해 작업을 삭제합니다.
실패한 작업을 삭제하는 것이 유용했기 때문에 사용자에게 더 나은 피드백을 제공할 수 있었습니다. 다양한 이유로 작업을 취소할 때는
그러한 방법이 없습니다. 사용자가 파이프라인이 실행되는 동안 컴퓨팅 크레딧이 부족하면 작업을 취소하거나 다른 파이프라인에 의해 자동으로 취소될 수 있기 때문입니다.
취소
및 실패
상황에 모두 stop_reason
대신 failure_reason
을 사용하고 취소
상태를 더 적절하게 사용할 수 있게 할 수 있도록
canceled
상태를 더 적절하게 사용할 수 있게 할 수 있습니다.
정보 2: 빈 상태
우리는 명확성을 위해 최근에 the when
keyword에 대한 문서를 업데이트했습니다.
on_success
: 이전 단계에서 실패한 작업이 없거나allow_failure: true
가 있는 경우에만 작업을 실행합니다.on_failure
: 이전 단계에서 적어도 하나의 작업이 실패할 경우에만 작업을 실행합니다.
예를 들어;
test1:
when: on_success
script: exit 0
# needs: [] would lead to the same result
test2:
when: on_failure
script: exit 0
# needs: [] would lead to the same result
-
test1
는 이전 단계에서 실패한 작업이 없으므로 실행됩니다. -
test2
는 이전 단계에서 실패한 작업이 없으므로 실행되지 않습니다.
on_success
는 “실패한 것이 없다”를 의미하며 모든 것이 성공했음을 의미하는 것은 아닙니다.
on_failure
도 “모든 것이 실패했다”를 의미하는 것은 아니지만 “무언가가 실패했다”는 것을 의미합니다.
이 의미론적인 면은 파이프라인이 성공한다는 기대에 의하여 설정되며 이는 기쁜 일입니다.
파이프라인이 실패한다는 것이 아니라 그러므로 이것은 사용자 개입을 필요로 합니다.
기술적인 기대
모든 제안이나 향후 결정은 다음 목표를 따라야 합니다.
-
allow_failure
키워드는 실패한 작업을 “경고와 함께 성공”으로 표시하는 데만 책임져야 합니다.- 이유: 매뉴얼 작업이 블로커인지 아닌지를 결정하는 등 다른 책임을 지도록 하면 안 됩니다.
- 방법: 매뉴얼 작업의 블로커 동작을 제어하기 위해 다른 키워드가 도입됩니다.
-
allow_failure
로 취소된 작업은 “경고와 함께 성공”으로 표시되어서는 안 됩니다.- 이유: “취소”는 “실패”와 다른 상태입니다.
- 방법:
allow_failure: true
로 취소된 작업은 “경고와 함께 성공”으로 표시되지 않습니다.
-
when
키워드는 단지 “무엇을 실행해야 하는가?”라는 질문에 대한 답을 해야 합니다. 그리고 이것은 작업을 파이프라인에 추가할지 여부를 결정하기 위한 유일한 진실이어야 합니다. -
when
키워드는 작업을 파이프라인에 추가할지 여부를 제어하지 않아야 합니다.- 이유: 이것은 그것의 책임이 아닙니다.
- 방법: 작업을 파이프라인에 추가할지 여부를 제어하기 위해 다른 키워드가 도입됩니다.
- “건너뛰기”와 “무시하기” 상태를 재고해야 합니다.
- TODO: 더 많이 논의할 필요가 있습니다.
- 새로운 키워드 구조를 도입하여 작업이 “자동”, “매뉴얼”, 또는 “지연” 작업인지 여부를 지정해야 합니다.
- 이유: 이것은
when
키워드의 책임이 아닙니다. - 방법: 작업의 동작을 제어하기 위해 새로운 키워드가 도입됩니다.
- 이유: 이것은
-
needs
키워드는 작업의 순서만을 제어해야 합니다. 작업의 동작을 제어하거나 작업을 실행할지 여부를 결정하는 데 사용해서는 안 됩니다.- 이유: 이것은 다른 동작을 유도하고 사용자를 혼란스럽게 합니다.
- 방법:
needs
키워드와dependencies
키워드는 상호배타적이어야 합니다. - 방법:
needs
와dependencies
키워드는 하나의 작업에서 함께 사용해서는 안 됩니다.
제안
N/A
디자인 및 구현 세부 정보
N/A