Status | Authors | Coach | DRIs | Owning Stage | Created |
---|---|---|---|---|---|
ongoing |
@ayufan
@fabiopitino
@grzesiek
|
@ayufan
@grzesiek
|
@dhershkovitch
@marknuzzo
| devops verify | 2022-09-14 |
CI/CD 카탈로그
요약
CI/CD 파이프라인 구성요소 카탈로그의 목표는 파이프라인 구성을 재사용하기를 더 쉽고 효율적으로 만드는 것입니다. 파이프라인 구성을 발견하고 이해하며 재사용 방법을 배울 수 있는 방법을 제공하여 더욱 무난한 경험을 제공합니다. 또한 CI/CD 파이프라인 구성요소 카탈로그는 사용자들이 파이프라인 구성요소에 대해 협력하고 발전시키며 시간이 지나면 개선할 수 있도록 하는 프레임워크를 설정합니다.
이 청사진은 파이프라인 구성요소의 카탈로그를 구축하는 데 대한 구조적인 지침을 정의합니다. 또한 이 청사진은 솔루션에 대한 이터레이션과 개선의 장기적 방향을 정의합니다.
과제
- GitLab CI/CD는 새로운 사용자에게는 높은 학습 곡선을 가질 수 있습니다. 사용자들은 파이프라인을 구성하는 방법을 이해하기 위해 문서와 YAML 참조를 읽어야 합니다.
- 개발자들은 기존의 CI/CD 템플릿을 재사용하는 데 어려움을 겪고 결국 휠을 다시 발명하여 YAML 구성을 반복해서 작성해야 합니다.
- GitLab CI 템플릿은 특정 목적을 위한 파이프라인 또는 작업 행위를 제공합니다. 그러나 현재 제품과 함께 제공되어 버전 관리가 어렵습니다. 자세한 내용은 이ssue를 참조하세요.
- GitLab CI/CD 사용자(파이프라인 작성자)는 현재 자체 공유 파이프라인 구성을 구성하는 데 고유한 아이디어를 가지고 있습니다. 이러한 구성은 대부분 문서화되지 않을 가능성이 높습니다.
- 발견 가능한 구성은 GitLab CI 템플릿 뿐입니다. 그러나 내부 문서화가 없으므로 실제 YAML 내용을 복사하여 편집기에서 내용을 읽지 않으면 사용 방법을 파악하기가 어렵습니다.
- 추가 GitLab 기능(CD, 보안, 테스트 등)을 도입하는 게 더 어렵습니다.
- 재사용 가능한 CI 구성을 테스트하기 위한 프레임워크가 없습니다. 많은 구성은 단일 변경에 대해 단위 테스트되지 않습니다.
- 공동체, 파트너, 제3자, 개인 기여자들은 GitLab 관리 템플릿에 기여하려면 GitLab 기여 프로세스를 통과해야 합니다. 자세한 내용은 이 issue를 참조하세요.
- GitLab은 추가된 후 거의 유지되지 않는 템플릿을 포함한 100개 이상의 템플릿을 보유하고 있습니다.
GitLab CI 템플릿에 대한 문제점
- GitLab CI 템플릿은 결정론적인 동작을 고려하여 설계되지 않았습니다.
- GitLab CI 템플릿은 재사용을 고려하여 설계되지 않았습니다.
-
Jobs/
템플릿은stage:
속성을 하드코딩하지만 템플릿 사용자는 어떤 스테이지가 필요한지를 미리 알아야 하거나 어떤 방식으로든 이를 무시해야 합니다.- 사용자는 주어진 단계 내에서 작업을 가져오거나 컴포넌트를 사용할 때 입력 매개변수로 스테이지 이름을 전달해야 합니다.
- 올바른 스테이지를 매핑하지 못하면 혼란스러운 오류가 발생할 수 있습니다.
- 일부 템플릿은 AutoDevOps에서 작동하도록 설계되었지만 충분히 일반적이지 않습니다 (예시).
- 많은 CI 템플릿, 특히 언어별 것들은 튜토리얼/프레임워크 스타일의 템플릿입니다.
- 사용자에게 일반적인 파이프라인이 어떻게 보일지 보여주려고 하는 것으로 사용자 관점에서 높은 사용자 정의가 필요합니다.
- 다른 UX가 필요합니다: 파이프라인 편집기 커서의 위치에 복사하여 붙여넣기.
-
SAST.latest.gitlab-ci.yml
와 같이 일부 템플릿은 동일한 파이프라인에 조건부로 여러 작업을 추가합니다.- 이러한 작업들은 이상적인 상황에서 자식 파이프라인으로 실행되어 부모 파이프라인에서 보고서를 사용할 수 있어야 합니다.
- 부모-자식 파이프라인을 사용하기 위해서 이 epic이 필요합니다.
- 일부 템플릿은
variables
,image
및 기타 최상위 키워드를 잘못 사용하지만 이는 템플릿에 정의된 작업뿐만 아니라 모든 파이프라인 작업에서 정의합니다.- 이러한 기술은 템플릿이 불필요하게 작업을 수정할 때 상속 문제를 도입합니다.
기회
- 사용자가 필요한 것을 검색하고 찾을 수 있는 파이프라인 구성 카탈로그가 있으면 새로운 사용자들에게 문턱이 훨씬 낮아질 수 있습니다.
- 고객들은 이미 자체 공유 구성의 카탈로그를 전개하려고 합니다. 제품에서 파이프라인 구성을 직접 쓰고 패키지화하고 공유할 수 있는 표준화된 방법을 제공할 수 있습니다.
- 새로운 파이프라인 구성(예: 재사용 가능한 작업 단계)을 구현할 때 이것들이 카탈로그의 항목이 될 수 있습니다. 카탈로그는 새로운 구성의 도입을 촉진시킬 수 있습니다.
- 카탈로그는 제휴사와의 관계를 강화할 수 있는 장소가 될 수 있습니다. 제품이 제공하고 유지되는 컴포넌트들이 있을 수 있습니다.
- 발견 가능성과 더 나은 버전 관리 메커니즘으로 더 많은 개선과 더 나은 협력이 가능합니다.
- 경쟁 환경에서 이러한 기능의 필요성이 나타나고 있습니다.
- R2DevOps은 GitLab 파이프라인의 CI 템플릿 카탈로그를 구현합니다.
- GitHub Actions은 재사용 가능한 작업 단계의 포괄적인 카탈로그 제공합니다.
- CircleCI Orbs는 재사용 가능한 YAML 구성 패키지를 제공합니다.
용어집
이 섹션에서는 이 문서 전반에서 사용되는 일부 용어를 정의합니다. 이 용어들은 추상적인 개념을 식별하기 위한 것이며 새로운 통찰을 발견함에 따라 변경될 수 있습니다.
-
구성요소는 재사용 가능한 파이프라인 구성의 일반적인 용어입니다. 이 구성요소는 템플릿(
include
구문을 통해 사용 가능) 또는 단계일 수 있습니다. - 구성요소 프로젝트는 1개 이상의 구성요소를 포함하는 GitLab 프로젝트입니다. 구성요소 프로젝트는 카탈로그에 나열될 수 있기 때문에 코드베이스에서 카탈로그 리소스로도 언급됩니다.
- 카탈로그는 구성요소 프로젝트들의 모음입니다.
- 버전은 카탈로그에 발행된 구성요소 프로젝트 릴리스입니다.
- 발행은 구성요소 프로젝트 릴리스를 카탈로그에 나열하는 행위입니다.
- 단계는 작업 실행 지침의 모음을 포함하는 구성요소 유형입니다.
- 템플릿은 프로젝트의 파이프라인 구성에 포함될 수 있는 CI/CD 구성의 조각입니다.
CI 컴포넌트
컴포넌트 정의
파이프라인 컴포넌트는 하나의 파이프라인 구성 단위를 추상화하는 재사용 가능한 단일 목적 빌딩 블록입니다. 컴포넌트는 파이프라인 구성의 일부 또는 전체를 구성하는 데 사용됩니다. 다양한 파이프라인 컨텍스트에서 적응 및 재사용 가능한 입력 매개변수를 선택적으로 적용할 수 있으며 구현 세부 정보를 캡슐화하고 격리할 수 있습니다.
컴포넌트를 사용하면 모든 세부 사항이 한 곳에 정의되는 대신 추상화를 사용하여 파이프라인을 조립할 수 있습니다. 파이프라인에서 컴포넌트를 사용할 때 사용자는 컴포넌트의 구현 세부 정보를 알 필요가 없으며 제공된 인터페이스에만 의존해야 합니다.
파이프라인 컴포넌트는 사용할 수 있는 파이프라인 구성의 컨텍스트를 나타내는 종류를 정의합니다. 예를 들어, X 유형의 컴포넌트는 X 유즈케이스에 따라 사용할 수 있습니다.
컴포넌트를 사용하는 시스템의 최상의 경험을 위해서는 컴포넌트가 다음을 준수해야합니다:
- 단일 목적: 컴포넌트는 단일 목표에 집중해야 하며 범위는 최소화되어야 합니다.
- 격리됨: 컴포넌트가 파이프라인에서 사용될 때, 구현 세부 사항이 컴포넌트 외부로 노출되어서는 안 되며 메인 파이프라인에 노출되어서도 안 됩니다.
- 재사용 가능: 컴포넌트는 다른 파이프라인에서 사용할 수 있도록 설계됩니다. 사용되는 가정에 따라 컴포넌트는 더 많거나 더 적게 일반적일 수 있습니다. 일반적인 컴포넌트는 재사용이 더 많이 가능하지만 더 많은 사용자 정의가 필요할 수 있습니다.
- 버전 관리: 컴포넌트를 사용할 때 관심 있는 버전을 명시해야 합니다. 버전은 컴포넌트의 정확한 인터페이스 및 동작을 식별합니다.
- 해결 가능: 컴포넌트가 다른 컴포넌트에 의존하는 경우 이 의존성은 명시적이고 추적 가능해야 합니다.
예측 가능한 컴포넌트
최종적으로 CI 카탈로그 컴포넌트를 예측 가능하게 만들고자 합니다. 고정된 @
버전을 사용하여 경로별로 컴포넌트를 포함하면 해당 컴포넌트가 포함된 컨텍스트에 관계없이 항상 동일한 구성을 반환해야 합니다.
주어진 컴포넌트 버전 및 include:inputs
키워드를 통해 전달된 입력 집합에 대해 결과 구성은 동일해야 하므로 결정론적이어야 합니다.
컴포넌트가 포함됨으로써 부작용을 일으키지 않아야 하며 참조 투명성이어야 합니다.
컴포넌트를 예측 가능하게 만드는 것은 과정이며, 현재 사용자 및 고객들에게 혼란을 줄 수 있으므로 CI 템플릿을 크게 재설계하지 않고는 이를 달성할 수 없을 수도 있습니다.
우리는 초기에 몇 가지 최상위 키워드, 예를 들어 include: remote:
를 제한하는 것을 고려했지만, 결국 컴포넌트를 더 예측 가능하게 만들기 위해 필요한 설계에 대해 더 잘 이해하기 위해 MVP에 대해 먼저 반복해야 한다는 결론에 이르렀습니다. 예측 가능성, 결정론성, 참조 투명성 및 CI 컴포넌트의 예측 가능성은 여전히 중요하지만 초기 반복에서는 이를 달성할 수 없을 수 있습니다.
컴포넌트 구조
파이프라인 컴포넌트는 <fqdn>/<component-path>@<version>
형식의 고유한 주소로 식별됩니다. 이 주소에는 다음이 포함됩니다:
- 완전한 FQDN (Fully Qualified Domain Name).
- 해당 부분을 정의하는 리포지터리 또는 디렉터리의 경로
- 특정 버전
예를 들어: gitlab.com/gitlab-org/dast@1.0
.
FQDN
최초에는 동일한 GitLab 인스턴스를 가리키는 컴포넌트 주소만 지원합니다. 즉, FQDN이 GitLab 호스트와 일치합니다.
컴포넌트 경로
컴포넌트 경로로 식별된 디렉터리에는 적어도 컴포넌트 YAML 파일과 관련 README.md
문서 파일이 선택적으로 포함되어 있어야 합니다.
컴포넌트 경로는 다음과 같을 수 있습니다:
- 프로젝트 경로:
gitlab.com/gitlab-org/dast
. 기본 컴포넌트가 처리됩니다. - 명시적 컴포넌트 경로:
gitlab.com/gitlab-org/dast/api-scan
. 이 경우 명시적인api-scan
컴포넌트가 처리됩니다. - 로컬 디렉터리의 상대적인 경로:
./path/to/component
. 이 경로에는 컴포넌트를 정의하는 컴포넌트 YAML이 포함되어야 합니다. 경로는 현재 파일 경로를 기준으로 상대적인 경로임을 나타내기 위해./
또는../
로 시작해야 합니다.
상대적인 로컬 경로는 전체 컴포넌트 주소의 약식 형식으로, 예를 들어 gitlab-org/dast
프로젝트의 mydir/file.yml
에서 호출된 ./path/to/component
는 다음과 같이 확장됩니다:
gitlab.com/gitlab-org/dast/mydir/path/to/component@<CURRENT_SHA>
컴포넌트 YAML 파일은 컴포넌트 유형 중 하나인 <type>.yml
파일명 규칙을 따라야 합니다:
컴포넌트 유형 | 컨텍스트 |
---|---|
template
|
include: 키워드하에 사용되는 컴포넌트용
|
컴포넌트가 사용되는 컨텍스트에 따라 올바른 YAML 파일을 가져옵니다. 예를 들어:
- 컴포넌트
gitlab.com/gitlab-org/dast@1.0
을 포함할 경우,gitlab-org/dast
리포지터리의 루트 디렉터리에template.yml
파일이 있어야 합니다. - 컴포넌트
gitlab.com/gitlab-org/dast/api-scan@1.0
을 포함할 경우,gitlab-org/dast
리포지터리의api-scan
디렉터리에template.yml
파일이 있어야 합니다.
컴포넌트 YAML 파일:
- 참조할 이름을 가져야 합니다.
- 파일 이름의 유형을 지정해야 합니다. 이것이 컴포넌트가 사용될 방식을 정의합니다 (
include
에 사용되는 원시 구성, 자식 파이프라인 워크플로우, 작업 단계). - 콘텐츠를 정의해야 합니다.
- 입력 매개변수를 명시해야 합니다. 컴포넌트는 동적 값에 대해 입력 매개변수에 의존해야 하며 환경 변수를 사용해서는 안 됩니다.
- 정적으로 유효성을 검사해야 합니다 (예: JSON 스키마 유효성 검사기 사용).
spec:
inputs:
website:
environment:
default: test
test_run:
options:
- unit
- integration
- system
---
# 컴포넌트의 내용
컴포넌트 버전
컴포넌트 버전은 다음 중 가장 높은 우선순위로 적용될 수 있습니다:
- 커밋 SHA - 예:
gitlab.com/gitlab-org/dast@e3262fdd0914fa823210cdb79a8c421e2cef79d8
- 태그 - 예:
gitlab.com/gitlab-org/dast@1.0
- 가장 최근에 공개된 릴리스를 가리키는 특수한 이동 대상 버전 - 예:
gitlab.com/gitlab-org/dast@~latest
- 브랜치 이름 - 예:
gitlab.com/gitlab-org/dast@master
태그와 브랜치에 동일한 이름이 있는 경우 태그가 브랜치보다 우선합니다. 마찬가지로 태그가 e3262fdd0914fa823210cdb79a8c421e2cef79d8
와 같은 이름을 가지고 있다면 (해당하는 경우) 커밋 SHA가 태그보다 우선합니다.
릴리스되지 않은 모든 리비전에 대한 참조를 원하는 경우 컴포넌트는 깃 리포지터리에 정의되어야 합니다.
로컬 경로별로 컴포넌트를 참조하는 경우 (예: ./path/to/component
), 해당 버전은 암시적이며 현재 파이프라인 컨텍스트의 커밋 SHA와 일치합니다.
~latest
버전
~latest
버전 한정자의 사용은 카탈로그에 게시된 릴리스만 해당됩니다.
우리는 ~latest
가 카탈로그 자원으로 표시되지 않은 프로젝트에 대해 지원되어야 하는지에 대해 논의했습니다.
이 결정에는 여러 가지 이유가 있습니다.
- 카탈로그에서 디렉터리에서 빠질 수 있고,
~latest
는 이를 반영해야 합니다. - 카탈로그는 비공개 자원을 지원할 것입니다. 현재 컴포넌트 프로젝트가 릴리스를 가지고 있지만 카탈로그에는 게시되지 않는 경우 유효한 요구 사항이 없습니다.
- 미래에는 릴리스하는 프로세스와 게시하는 릴리스를 분리하여 사용자가 카탈로그에 어떤 릴리스를 게시할지 선택할 수 있도록 할 것입니다.
- 릴리스를 게시할 때 의미 있는 버전 관리를 강제할 수 있으며, 표준을 따르지 않으면 거부됩니다. 릴리스 모델에서 의미 있는 버전 관리를 강제할 수 없기 때문에 이는 하위 호환성이 없을 것입니다.
- 최신 버전은 카탈로그 자원 데이터 구조의 비정규화로, 카탈로그 자원을 표시하고 컴포넌트 버전을 검색할 때 보다 성능이 우수한 쿼리를 지원할 것입니다.
위의 모든 점에서 카탈로그 자원과 미게시된 컴포넌트 프로젝트 모두를 위해 ~latest
를 지원한다면 불일치하고 예상치 못한 동작을 일으킬 수 있습니다. 게시된 버전만 지원하는 엄격한 접근 방식으로 시작함으로써, 미래에는 사용자 요구에 따라 미게시된 컴포넌트 프로젝트를 지원하는 방향으로 확장할 수 있는 자유를 가지게 됩니다.
미래 자원 유형에 관한 참고
미래에 카탈로그에서 여러 유형의 자원을 지원하기 위해 프로젝트의 루트 디렉터리에 catalog-resource.yml
파일이 정의되어야 할 것입니다.
name: DAST
description: 웹 엔드포인트를 검사하여 취약점 찾기
category: 보안
tags: [동적 분석, 보안 스캐너]
type: components_repository
이 파일은 리소스 내용에 대한 메타데이터를 색인화하는 데도 사용될 수 있습니다. 예를 들어, 사용자는 리포지터리에 포함된 컴포넌트들을 나열할 수 있고, 우리는 검색용으로 추가 데이터를 색인화할 수 있습니다.
name: DAST
description: 웹 엔드포인트를 검사하여 취약점 찾기
category: 보안
tags: [동적 분석, 보안 스캐너]
type: components_repository
metadata:
components:
- all-scans
- scan-x
- scan-y
입력 매개변수
컴포넌트가 어떤 입력 매개변수를 받는지는 다음 스키마에 따라 명시되어야 합니다.
spec:
inputs:
website: # 기본적으로 선언된 모든 입력은 필수입니다.
environment:
default: test # 제공되지 않으면 기본값 적용. 이렇게 하면 입력이 선택적입니다.
flags:
default: null # 값을 제공하지 않고 전체 입력을 선택적으로 만듭니다.
test_run:
options: # 기본값이 없으므로 디렉터리에서 선택해야 합니다.
- unit
- integration
- system
이 경우 YAML에는 2개의 문서가 포함되어 있습니다. 첫 번째 문서는 명세를 나타내고, 두 번째 문서는 내용을 나타냅니다.
컴포넌트를 사용할 때 입력 매개변수를 다음과 같이 전달합니다.
include:
- component: gitlab.com/org/my-component@1.0
inputs:
website: ${MY_WEBSITE} # 변수 확장
test_run: system
environment: $[[ inputs.environment ]] # 상위 입력 내용 보간
include:inputs
구문은 변수 확장을 지원해야 하며, 상위에서 제공된 입력 매개변수의 보간도 가능해야 합니다.
입력 매개변수는 가능한 한 빨리 유효성을 검사합니다.
-
org/my-component
프로젝트 내의gitlab-template.yml
파일을 읽습니다. - 명세에서
spec:inputs
를 구문 분석하고 매개변수를 이 스키마와 대조합니다. - 성공적으로 검증되면 내용을 구문 분석하여 진행합니다. 그렇지 않으면 오류를 반환합니다.
- 컴포넌트의 내용 내에서 입력 매개변수를 보간합니다.
spec:
inputs:
environment:
options: [test, staging, production]
---
"run-tests-$[[ inputs.environment ]]":
script: ./run-test
scan-website:
script: ./scan-website $[[ inputs.environment ]]
rules:
- if: $[[ inputs.environment ]] == 'staging'
- if: $[[ inputs.environment ]] == 'production'
$[[ inputs.XXX ]]
를 사용하여 입력은 내용 구문 분석 직후 즉시 보간됩니다.
CI 구성 보간 관점 및 제한 사항
spec:inputs
로 사용자는 CI 구성을 위한 입력 인수를 정의할 수 있습니다.
include:inputs
로는 이러한 인수를 CI 구성으로 전달할 수 있습니다.
$[[ inputs.something ]]
의 inputs
는 보간 블록에서 사용자가 자신의 인수에 액세스할 수 있도록 제공할 초기 “객체” 또는 “컨테이너”가 될 것입니다. 그러나 이는 다음과 같은 여러 가지 방향으로 발전할 수 있습니다.
- 보다 쉽게 환경 변수에 액세스할 수 있도록
variables
또는env
객체를 제공할 수 있습니다. - 블록 평가를 확장하여 다른 곳에서 전달된 JSON 또는 YAML 객체를 더 쉽게 탐색할 수 있게 할 수 있습니다.
- 리포지터리 파일, 스니펫 또는 이쪽에 있는 문제에 대한 액세스도 제공할 수 있습니다.
CI 구성 보간은 상대적으로 계산 집약적인 기술입니다. 특히 GitLab.com에서 이 메커니즘이 빈번하게 사용될 것으로 예상하기 때문에, 우리는 운영 시스템을 안전하게 유지하기 위해 여러 가지 제한 사항을 도입했습니다. 이러한 제한 사항은 사용자에게 올바르게 사용하도록 보장하기 위한 것으로, 일반적으로 다른 수준의 애플리케이션 제한 사항(지원되는 최대 YAML 크기, YAML 파일 구문 분석 제한 시간 등)이 있기 때문에 사용자에게 영향을 주지 않아야 합니다. 그 중 일부는 다음과 같습니다.
- 보간 블록 크기는 1 킬로바이트를 넘을 수 없습니다.
- 보간을 포함하는 YAML 값의 크기는 1메가바이트를 초과할 수 없습니다.
- YAML 구성은 50만 개 항목을 넘을 수 없습니다.
왜 입력 매개변수이고 환경 변수가 아닌가요?
오늘까지 우리는 정보를 전달하기 위해 환경 변수를 활용해 왔습니다. 예를 들어, 상위 파이프라인에서 하위 파이프라인으로 정보를 전달하기 위해 환경 변수를 사용하고 있습니다.
컴포넌트로 정보를 전달하기 위해 환경 변수를 사용하는 것은 프로그래밍 언어에서 전역 변수를 선언하는 것과 비슷합니다. 선언하는 변수가 많을수록 변수 충돌 가능성이 높아지고 변수 범위가 넓어집니다.
입력 매개변수는 컴포넌트로 전달되는 변수와 같이 특정 범위 내에 존재하는 매개변수입니다. 그리고 이러한 매개변수는 외부로 노출되지 않는다는 특징을 가지고 있습니다. 입력 매개변수는 상속되지 않습니다. 명시적으로 전달되어야 합니다.
이 패러다임을 통해 강력하고 격리된 컴포넌트를 더 쉽게 만들고 선언하며 계약을 강제할 수 있습니다.
기존 include:
구문에 대한 입력 매개변수
include:component
를 통해 구성요소에 입력 매개변수를 추가하기 때문에 다른 include:
유형을 통해 inputs:
구문을 지원할 수 있는 기회가 있습니다:
include:
- component: gitlab.com/org/my-component@1.0
inputs:
foo: bar
- local: path/to/file.yml
inputs:
foo: bar
- project: org/another
file: .gitlab-ci.yml
inputs:
foo: bar
- remote: http://example.com/ci/config
inputs:
foo: bar
- template: Auto-DevOps.gitlab-ci.yml
inputs:
foo: bar
그런 다음 포함되는 구성은 YAML의 섹션을 정의하여 입력을 지정해야 합니다:
spec:
inputs:
foo:
---
# 구성의 나머지 부분
YAML이 include:inputs
를 사용하여 내용을 포함하지만 포함하는 YAML이 명세에 spec:inputs
를 정의하지 않은 경우 오류가 발생해야 합니다.
include:inputs
| spec:inputs
| 결과 |
---|---|---|
지정됨 | 오류 발생 | |
지정됨 | 지정됨 | 입력 유효성 검사 |
지정됨 | 기본값 사용 | |
입력 전달 없이 이전 include:
|
파이프라인의 입력 매개변수
입력은 트리거될 때 파이프라인으로 매개변수를 전달하는 데에도 사용할 수 있으며 즉시 유효성을 누릴 수 있습니다.
오늘날 우리는 몇 가지 사용 사례가 있습니다. 명시적인 입력 매개변수를 사용하는 것이 유익할 것입니다:
-
Run Pipeline
UI 폼.-
현재 문제점: 우리는
variables:*:description
을 사용하여 환경 변수를 UI에 노출시킵니다. 이것의 문제는 책임의 혼합과 선순위의 점프가 있어서이며 YAML 변수에서 파이프라인 변수로의 변수가됩니다. 이러한 솔루션에 대한 유효성 검사 및 기능 구축은 도전적이고 복잡합니다.
-
현재 문제점: 우리는
- API를 통해 파이프라인을 트리거. 예를 들어
{ inputs: { provider: 'aws' } }
와 함께POST /projects/:id/pipelines/trigger
. -
trigger:
구문을 사용하여 파이프라인을 트리거합니다.
deploy-app:
trigger:
project: org/deployer
inputs:
provider: aws
deploy_environment: staging
Run Pipeline
UI 폼 문제를 해결하기 위해 우리는 완전히 inputs
사양을 활용할 수 있을 것입니다:
spec:
inputs:
concurrency:
default: 10 # 입력 상자에 기본값으로 표시됩니다
provider: # 폼 유효성 검사에서 `required`를 강제화할 수 있음
description: 배포 공급자 # 옵션: 입력 레이블로 렌더링합니다.
deploy_environment:
options: # 아래에 정의된 순서대로 선택 상자를 렌더링함
- staging # 1번 옵션
- canary # 2번 옵션
- production # 3번 옵션
default: staging # UI에서 기본적으로 선택됨
# `default:`가 지정되지 않은 경우 사용자는 명시적으로 옵션을 선택해야 합니다.
description: 배포 환경 # 옵션: 입력 레이블로 렌더링합니다.
---
# 파이프라인 구성의 나머지 부분
컴포넌트 리포지터리
컴포넌트 리포지터리는 하나 이상의 파이프라인 컴포넌트를 독점적으로 호스팅하는 GitLab 프로젝트/리포지터리입니다.
컴포넌트 리포지터리는 카탈로그 리소스가 될 수 있습니다. 컴포넌트 리포지터리에는 카탈로그에 나열하지 않아도 권장되지만, 앵커와 프로젝트 설명을 설정하여 발견성을 향상시킬 것을 권장합니다.
카탈로그에 나열된 컴포넌트 리포지터리는 리포지터리의 루트 디렉터리에 README.md
파일을 가져야 합니다.
README.md
은 컴포넌트 리포지터리의 문서를 나타내므로 카탈로그에 나열하지 않을 때에도 권장됩니다.
컴포넌트 리포지터리의 구조
컴포넌트 리포지터리에는 하나 이상의 컴포넌트를 호스트할 수 있습니다. 작성자는 단일 컴포넌트 또는 동일한 리포지터리에 여러 일관된 컴포넌트를 포함할지 여부를 결정할 수 있습니다.
컴포넌트 리포지터리는 프로젝트의 전체 경로로 식별됩니다.
예를 들어 Rails 앱의 RSpec 테스트를 실행하는 컴포넌트를 개발 중이라고 상상해 봅시다. myorg/rails-rspec
라는 프로젝트를 생성했습니다.
다음 디렉터리 구조는 리포지터리당 1개의 컴포넌트를 지원할 것입니다:
.
├── template.yml
├── README.md
└── .gitlab-ci.yml
변경 사항이 적절히 검증되도록 하기 위해 .gitlab-ci.yml
이 프로젝트에서 권장됩니다.
이제 이 컴포넌트는 경로 gitlab.com/myorg/rails-rspec
로 식별되며
또한 프로젝트 경로에 매핑됩니다. 루트 디렉터리에 template.yml
파일과 README.md
가 있어야 한다고 예상합니다.
다음 디렉터리 구조는 리포지터리당 여러 유형의 컴포넌트를 지원할 것입니다:
.
├── .gitlab-ci.yml
├── README.md
├── unit/
│ └── template.yml
├── integration/
│ └── template.yml
└── feature/
└── template.yml
이 예에서는 RSpec로 실행되는 여러 테스트 프로파일을 정의하고 있습니다. 사용자는 이 중 하나 이상을 선택해서 사용할 수 있을 것입니다.
이러한 각각의 컴포넌트는 경로 gitlab.com/myorg/rails-rspec/unit
, gitlab.com/myorg/rails-rspec/integration
,
gitlab.com/myorg/rails-rspec/feature
에 의해 식별됩니다.
이 디렉터리 구조는 두 가지 전략 모두 지원할 수 있습니다:
.
├── template.yml # myorg/rails-rspec
├── README.md
├── LICENSE
├── .gitlab-ci.yml
├── unit/
│ └── template.yml # myorg/rails-rspec/unit
├── integration/
│ └── template.yml # myorg/rails-rspec/integration
└── feature/
└── template.yml # myorg/rails-rspec/feature
위의 구조를 사용하면 최상위 컴포넌트를 사용하여 기본 컴포넌트로 설정할 수 있습니다.
예를 들어 myorg/rails-rspec
는 모든 테스트 프로필을 함께 실행할 수 있을 것입니다.
그러나 더 구체적인 테스트 프로필은 별도로 사용할 수 있을 것입니다 (예: myorg/rails-rspec/integration
).
CI 카탈로그
CI 카탈로그는 사용자가 CI/CD에서 활용할 수 있는 리소스의 디렉터리입니다. 초기에는 사용자가 발견하고 파이프라인에서 사용할 수 있는 컴포넌트 리포지터리의 디렉터리이 포함되어 있습니다. 사용자는 자신의 권한과 프로젝트 가시성 수준에 기초하여 리소스만 볼 수 있습니다. 인증되지 않은 사용자는 공개 리소스만 볼 수 있을 것입니다.
프로젝트 관리자는 프로젝트를 비공개 또는 공개로 설정하는 것에 대한 책임이 있습니다. CI 카탈로그는 프로젝트가 커뮤니티 카탈로그에 나타나는 것을 방지하는 등의 보안 기능을 제공해서는 안 됩니다. 프로젝트가 공개되면 결국 세계에서 보이게 되기 때문입니다.
카탈로그 페이지는 사용자 검색을 좀 더 정제하기 위한 다양한 필터를 제공할 수 있습니다. 그룹에서 리소스를 더 세부적으로 필터링할 수 있는 리소스와 같은 사전 정의된 필터를 포함합니다.
앞으로 카탈로그는 컴포넌트 리포지터리의 디렉터리 외에도 다른 유형의 리소스(예: 통합, 프로젝트 템플릿, 컨테이너 이미지 등)를 포함할 수 있습니다.
카탈로그에 컴포넌트 리포지터리를 나열하려면 프로젝트를 카탈로그 리소스로 표시해야 합니다. 이를 위해 초기에 프로젝트 설정을 사용합니다.
프로젝트가 “카탈로그 리소스”로 표시되면 최종적으로 카탈로그에 표시될 수 있을 것입니다.
설정이 활성화되면 데이터베이스 레코드를 생성하고 동일한 설정이 비활성화될 때 레코드 상태를 수정할 수 있을 것입니다.
카탈로그 자원
공개시, 카탈로그 자원은 적어도 다음 속성을 갖추어야 합니다:
-
path
: 고유하게 식별되어야 함. -
name
: 컴포넌트 리포지터리의 경우 프로젝트 이름일 수 있습니다. -
documentation
: 우리는 의무적으로README.md
파일을 사용할 것입니다. -
versions
: 자원의 하나 이상의 릴리스.
카탈로그 자원의 다른 속성:
-
description
: 컴포넌트 리포지터리의 경우 프로젝트 설명일 수 있습니다. -
avatar image
: 프로젝트 아바타를 사용할 수 있습니다. - 인기 지표 (별, 포크).
- 분류: 사용자는 카테고리를 선택하거나 검색 태그를 정의해야 합니다.
초기적으로, 프로젝트의 자원은 릴리스된 태그를 가지지 않을 수 있습니다. 사용자는 버전을 지정하여 컴포넌트 리포지터리를 사용할 수 있으며, 그 방법은 브랜치 이름이나 커밋 SHA를 지정함으로써 가능합니다. 그러나 이러한 유형의 버전 한정자들은 다양한 이유로 카탈로그 자원 페이지에 나열되어서는 안 됩니다:
- 브랜치와 태그 디렉터리이 매우 커질 수 있습니다.
- 브랜치와 태그는 최종 사용자에게 의미가 없을 수 있습니다.
- 브랜치와 태그는 버전 관리를 충분히 전달하지 못할 수 있습니다.
카탈로그에 카탈로그 자원을 나열하려면 우리는 먼저 프로젝트에 대한 릴리스를 생성해야 합니다.
카탈로그에 새로운 자원 버전 릴리스
자원에 대해 발행될 버전은 프로젝트 릴리스여야 합니다. 프로젝트 릴리스를 생성하는 것은 자원을 버전화하는 공식적인 행위입니다.
자원 페이지는 다음을 포함할 것입니다:
- 증거가 있는 최신 릴리스 (예: 기본 버전).
- 자원의 지난 릴리스를 확인하고 사용할 수 있는 능력.
-
README.md
로 표현된 문서.
사용자는 CI 파이프라인 작업에서 자원의 새 버전을 릴리스할 수 있어야 하며, 이는 지속적인 전달 원칙을 따르는 소프트웨어가 어떻게 배포되는지와 유사합니다.
컴포넌트 리포지터리 및 포함된 컴포넌트가 품질 기준을 충족하는지 확인하기 위해 사용자들은 자원의 새 버전을 릴리스하기 전에 테스트할 수 있습니다.
새로운 자원 버전의 릴리스 중에 실행할 수 있는 몇 가지 검사 예시:
- 프로젝트가 루트 디렉터리에
README.md
를 포함하는지 확인합니다. - 프로젝트 설명이 존재하는지 확인합니다.
- 컴포넌트 리포지터리에 사용 가능한 컴포넌트의 색인이 있는 경우, 각 컴포넌트가 유효한 YAML을 가지고 있는지 확인합니다.
프로젝트에 대한 새 릴리스가 생성되면 자원의 메타데이터를 색인화합니다. 우리는 초기에 가능한 한 많은 메타데이터를 색인화하여 CI 카탈로그의 주요 페이지를 설계할 때 더 많은 유연성을 확보하고 싶습니다. 우리는 CI 카탈로그에서 자원을 올바르게 시각화하기 위한 데이터 부족으로 제한받고 싶지 않습니다. 이를 위해 릴리스되는 모든 자원을 찾아 데이터와 메타데이터를 색인화해야 할 수도 있습니다.
예시: CI 컴포넌트의 spec:
섹션의 내용을 색인화합니다.
컴포넌트 리포지터리의 개발 워크플로우에 대한 예시를 확인하세요.
GitLab이 유지하는 카탈로그 자원
GitLab은 모든 SaaS 프로젝트에서 사용할 카탈로그 자원을 제공합니다. 이러한 프로젝트의 소유권을 명확히 전달하기 위해 해당 프로젝트는 components
최상위 그룹 내에 위치합니다.
추가로, 우리는 해당 프로젝트를 검증된 생성자
로 표시하여 신뢰도를 높이고자 합니다.
components
그룹은 단순히 개발 공간뿐만 아니라 GitLab 제품의 기능입니다.
GitLab 어디에서나 이 그룹 내의 컴포넌트를 참조할 수 있습니다.
components
아래의 각 프로젝트는 관련 제품 범주를 유지하는 팀에 의해 명시적으로 소유되어야 합니다. 예를 들어: SAST와 관련된 컴포넌트는 SAST 제품을 유지하는 팀이 소유합니다.
다른 주요 대안으로 고려된 것은 다음과 같습니다:
-
gitlab-org/gitlab-components
의 하위 그룹.- 이는 이 그룹을 소유하고 있는 사람을 명확히 해준다는 장점이 있습니다 (GitLab 조직).
- 이것의 단점은 번거로운 경로와 컴포넌트가 제품의 기능이기 때문에 간략한 경로가 충분하고, SaaS의 컴포넌트가 Self-managed 인스턴스에서 가져올 수 있어야 한다는 점입니다. 또한,
gitlab-org
출신 그룹은 혼동을 일으키고 이름 충돌에 민감합니다.
- 새로운 최상위 그룹
gitlab-components
.- 이는 덜 번거로운 경로를 가지고 있다는 장점이 있지만,
gitlab-
접두어가 중복되었습니다. - 기존의 GitLab 그룹에 이미 적용된 보안 및 규정 준수 기준을 복제해야 합니다. 그러나 그것은 여전히
components
그룹에 대한 별도의 개발 환경을 필요로 하여components
그룹은 GitLab 제품의 일부이기 때문에 이것은 상충됩니다.
- 이는 덜 번거로운 경로를 가지고 있다는 장점이 있지만,
- 커뮤니티 기여자가 사용하는 기존
gitlab-community/cicd-components
.- 장점은 이미 AppSec가 이 그룹에 대한 보안 및 규정 준수를 제어하고 있다는 것입니다.
- 단점은
gitlab-community
가 주로gitlab-org
에서 포크를 포함하고 있고, 이것이 혼란스러울 수 있다는 것입니다.
구현 지침
- 가장 작은 사용자 베이스로 시작하십시오.
gitlab-org
및gitlab-com
그룹을 위한 기능 사용을 익숙해 하십시오. 엔지니어링 프로덕션성 및 기타 그룹을 포함하여 파이프라인 구성을 작성하는 것이 초기 솔루션을 테스트하고 유효성을 검사하는 데 도움이 됩니다. - 수집한 모든 피드백을 통합할 수 있도록 보장하십시오. 초기 도입자와 명확한 기대를 갖고 기능을 일반 공개(GA)하기 전까지 피드백을 수용하십시오.
- 초기 반복에서 가능한 한 기존 기능을 재사용하십시오. 초기 반복에서 바퀴를 재창조하지 마십시오. 예를 들어: 제목, 설명, 아바타 같은 프로젝트 기능을 재사용하여 카탈로그를 작성합니다.
- 컴포넌트의 개발 수명주기에 대한 GitLab의 기능을 활용하십시오 (
.gitlab-ci.yml
을 통한 테스트, 릴리스 관리, 파이프라인 편집기 등). - Self-managed되는 지원을 위해 카탈로그 및 워크플로우를 설계하십시오.
- 카탈로그 및 워크플로우가 미래 형태의 파이프라인 구성 및 새로운 사용 방법을 지원할 수 있도록 하십시오.
- 결정론적 패키지 관리자를 구축하는 데 관련된 산업 최고의 실천 방법에 따라 컴포넌트 및 카탈로그를 설계하십시오.
반복
최초의 반복 계획은 다음과 같습니다:
- 실험 단계
-
namespace
액터와 함께 피처 플래그 뒤에 MVC를 구축합니다. - 도식화된 솔루션 및 피드백에 기반한 UX를 향상시킵니다.
- 이 기능을 일찍 도입할 초기 수용자를 찾고 이들의 피드백을 반복합니다.
-
- 새로운 파이프라인 구성 설계 (다른 단계와 병행)
- 새 파이프라인 구성에 대한 제안에 대해 기술 및 설계 프로세스를 시작합니다 (단계, 워크플로우, 템플릿).
- 새로운 구성을 구현합니다. 카탈로그는 그것들과 호환되어야 합니다.
- 새로운 구성을 사용하고 피드백을 반복합니다.
- 비공개 카탈로그에서 새로운 구성을 릴리스합니다.
- 권위 있는 계획을 가진 그룹을 위한 비공개 카탈로그 릴리스
- 피드백을 반복합니다.
- 모든 GitLab 사용자를 위한 공개 카탈로그 릴리스 (전망 기능)
- 새로운 GitLab CI 템플릿 버전을 구성요소로써 릴리스합니다.
- Self-managed되는 관리자들이 GitLab.com이나 리포지터리 익스포트로부터 구성요소를 가져와 자체 카탈로그를 채웁니다.
- 피드백을 반복합니다.
2023년 10월에 네임스페이스 뷰 (이전에 개인 카탈로그 뷰로 불림)를 실험으로 릴리스한 후에 우리는 두 개의 별도 뷰 (네임스페이스 뷰와 글로벌 뷰)에서 멀어져 유저 경험 (UX)를 하나의 글로벌 뷰로 통합하는 방향으로 초점을 전환했습니다.
한계
기능을 노출하는 모든 MVC는 처음부터 제한 사항을 추가해야 합니다. 새로운 기능을 제한적으로 추가하는 것이, 기능을 사용한 후에 제한하는 것보다 안전합니다. 사용자 요구에 따라 제한을 나중에 완화할 수 있습니다.
추가할 수 있는 몇 가지 제한 사항은 다음과 같습니다:
- 단일 프로젝트가 포함/내보낼 수 있는 컴포넌트의 수
-
.gitlab-ci.yml
파일이 사용할 수 있는 가져오기(import)의 수 - 컴포넌트가 선언/사용할 수 있는 가져오기(import)의 수
- 중첩된 가져오기(import)의 최대 레벨
- 내보낸 컴포넌트의 최대 길이
누구
제안:
역할 | 누구 |
---|---|
작성자 | Fabio Pitino |
엔지니어링 리더 | Cheryl Li, Mark Nuzzo |
제품 매니저 | Dov Hershkovitch |
아키텍처 진화 코치 | Kamil Trzciński, Grzegorz Bizon |
책임 담당자:
역할 | 누구 |
---|---|
리더십 | Mark Nuzzo |
제품 | Dov Hershkovitch |
엔지니어링 | Fabio Pitino |
사용자 경험 | Sunjung Park |
도메인 전문가:
영역 | 누구 |
---|---|
검증 / 파이프라인 작성 | Avielle Wolfe |
검증 / 파이프라인 작성 | Laura Montemayor |