This page contains information related to upcoming products, features, and functionality. It is important to note that the information presented is for informational purposes only. Please do not rely on this information for purchasing or planning purposes. The development, release, and timing of any products, features, or functionality may be subject to change or delay and remain at the sole discretion of GitLab Inc.
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
  • buildwhen: on_failure이기 때문에 이전 상태가 “실패”가 아니기 때문에 건너뛰어집니다.
  • test는 “건너뛰기”가 성공적인 상태이기 때문에 실행됩니다.

또는;

build1:
  stage: build
  script: exit 0
  when: on_failure

build2:
  stage: build
  script: exit 0

test:
  stage: test
  script: exit 0
  • build1when: 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_failurewhen: 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도 “모든 것이 실패했다”를 의미하는 것은 아니지만 “무언가가 실패했다”는 것을 의미합니다. 이 의미론적인 면은 파이프라인이 성공한다는 기대에 의하여 설정되며 이는 기쁜 일입니다. 파이프라인이 실패한다는 것이 아니라 그러므로 이것은 사용자 개입을 필요로 합니다.

기술적인 기대

모든 제안이나 향후 결정은 다음 목표를 따라야 합니다.

  1. allow_failure 키워드는 실패한 작업을 “경고와 함께 성공”으로 표시하는 데만 책임져야 합니다.
    • 이유: 매뉴얼 작업이 블로커인지 아닌지를 결정하는 등 다른 책임을 지도록 하면 안 됩니다.
    • 방법: 매뉴얼 작업의 블로커 동작을 제어하기 위해 다른 키워드가 도입됩니다.
  2. allow_failure취소된 작업은 “경고와 함께 성공”으로 표시되어서는 안 됩니다.
    • 이유: “취소”는 “실패”와 다른 상태입니다.
    • 방법: allow_failure: true로 취소된 작업은 “경고와 함께 성공”으로 표시되지 않습니다.
  3. when 키워드는 단지 “무엇을 실행해야 하는가?”라는 질문에 대한 답을 해야 합니다. 그리고 이것은 작업을 파이프라인에 추가할지 여부를 결정하기 위한 유일한 진실이어야 합니다.
  4. when 키워드는 작업을 파이프라인에 추가할지 여부를 제어하지 않아야 합니다.
    • 이유: 이것은 그것의 책임이 아닙니다.
    • 방법: 작업을 파이프라인에 추가할지 여부를 제어하기 위해 다른 키워드가 도입됩니다.
  5. “건너뛰기”와 “무시하기” 상태를 재고해야 합니다.
    • TODO: 더 많이 논의할 필요가 있습니다.
  6. 새로운 키워드 구조를 도입하여 작업이 “자동”, “매뉴얼”, 또는 “지연” 작업인지 여부를 지정해야 합니다.
    • 이유: 이것은 when 키워드의 책임이 아닙니다.
    • 방법: 작업의 동작을 제어하기 위해 새로운 키워드가 도입됩니다.
  7. needs 키워드는 작업의 순서만을 제어해야 합니다. 작업의 동작을 제어하거나 작업을 실행할지 여부를 결정하는 데 사용해서는 안 됩니다.
    • 이유: 이것은 다른 동작을 유도하고 사용자를 혼란스럽게 합니다.
    • 방법: needs 키워드와 dependencies 키워드는 상호배타적이어야 합니다.
    • 방법: needsdependencies 키워드는 하나의 작업에서 함께 사용해서는 안 됩니다.

제안

N/A

디자인 및 구현 세부 정보

N/A