튜토리얼: 복잡한 파이프라인 만들기
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
이 튜토리얼에서는 작은 반복적인 단계를 통해 점진적으로 더 복잡한 CI/CD 파이프라인을 구성하는 방법을 안내합니다. 이 튜토리얼을 완료하면 GitLab.com에 새 프로젝트가 생기고 Docusaurus를 사용하는 작동하는 문서 사이트를 갖게 됩니다.
이 튜토리얼에서는 작은 반복적인 단계를 통해 점진적으로 더 복잡한 CI/CD 파이프라인을 구성하는 방법을 안내합니다. 파이프라인은 항상 완전히 기능하지만 각 단계마다 더 많은 기능을 갖추게 됩니다. 목표는 문서 사이트를 빌드, 테스트 및 배포하는 것입니다.
이 튜토리얼을 완료하면 GitLab.com에 새 프로젝트가 생기고 Docusaurus를 사용하는 작동하는 문서 사이트를 갖게 됩니다.
이 튜토리얼을 완료하려면 다음을 수행합니다:
- Docusaurus 파일을 보관할 프로젝트 만들기
- 초기 파이프라인 구성 파일 만들기
- 사이트를 빌드하는 Job 추가
- 사이트를 배포하는 Job 추가
- 테스트 Job 추가
- 머지 리퀘스트 파이프라인 사용 시작
- 중복 구성 줄이기
사전 요구 사항#
- GitLab.com 계정이 필요합니다.
- Git에 익숙해야 합니다.
- 로컬 머신에 Node.js가 설치되어 있어야 합니다. 예를 들어 macOS에서는
brew install node로 node를 설치할 수 있습니다.
Docusaurus 파일을 보관할 프로젝트 만들기#
파이프라인 구성을 추가하기 전에 먼저 GitLab.com에 Docusaurus 프로젝트를 설정해야 합니다:
-
사용자 이름 아래에(그룹이 아닌) 새 프로젝트를 만듭니다:
- 오른쪽 상단 모서리에서 Create new(+)와 New project/repository를 선택합니다.
- Create blank project를 선택합니다.
- 프로젝트 세부 정보를 입력합니다:
- Project name 필드에 프로젝트 이름을 입력합니다. 예:
My Pipeline Tutorial Project. - Initialize repository with a README를 선택합니다.
- Project name 필드에 프로젝트 이름을 입력합니다. 예:
- Create project를 선택합니다.
-
프로젝트 개요 페이지의 오른쪽 상단 모서리에서 Code를 선택하여 프로젝트의 클론 경로를 찾습니다. SSH 또는 HTTP 경로를 복사하고 해당 경로를 사용하여 프로젝트를 로컬로 클론합니다.
예를 들어 SSH로 컴퓨터의
pipeline-tutorial디렉토리에 클론하려면:git clone git@gitlab.com:my-username/my-pipeline-tutorial-project.git pipeline-tutorial -
프로젝트 디렉토리로 이동한 후 새 Docusaurus 사이트를 생성합니다:
cd pipeline-tutorial npm init docusaurusDocusaurus 초기화 마법사가 사이트에 대한 질문을 표시합니다. 모든 기본 옵션을 사용합니다.
-
초기화 마법사가
website/에 사이트를 설정하지만 사이트는 프로젝트 루트에 있어야 합니다. 파일을 루트로 이동하고 이전 디렉토리를 삭제합니다:mv website/* . rm -r website -
GitLab 프로젝트 세부 정보로 Docusaurus 구성 파일을 업데이트합니다.
docusaurus.config.js에서:url:을https://<my-username>.gitlab.io/형식의 경로로 설정합니다.baseUrl:을/my-pipeline-tutorial-project/처럼 프로젝트 이름으로 설정합니다.
-
변경 사항을 커밋하고 GitLab에 푸시합니다:
git add . git commit -m "Add simple generated Docusaurus site" git push origin
초기 CI/CD 구성 파일 만들기#
가장 간단한 파이프라인 구성 파일로 시작하여 프로젝트에서 CI/CD가 활성화되어 있고 Job을 실행할 러너가 사용 가능한지 확인합니다.
이 단계에서는 다음을 소개합니다:
- Job: 명령을 실행하는 파이프라인의 독립적인 부분입니다. Job은 GitLab 인스턴스와 별도로 러너에서 실행됩니다.
script: Job 구성의 이 섹션에서는 Job의 명령을 정의합니다. 여러 명령(배열)이 있는 경우 순서대로 실행됩니다. 각 명령은 CLI 명령으로 실행된 것처럼 실행됩니다. 기본적으로 명령이 실패하거나 오류를 반환하면 Job이 실패로 플래그 지정되고 더 이상 명령이 실행되지 않습니다.
이 단계에서 프로젝트 루트에 다음 구성으로 .gitlab-ci.yml 파일을 만듭니다:
test-job:
script:
- echo "This is my first job!"
- date
이 변경 사항을 GitLab에 커밋하고 푸시한 후:
- Build > Pipelines로 이동하여 이 단일 Job으로 GitLab에서 파이프라인이 실행되는지 확인합니다.
- 파이프라인을 선택한 다음 Job을 선택하여 Job 로그를 보고 날짜가 표시된
This is my first job!메시지를 확인합니다.
이제 프로젝트에 .gitlab-ci.yml 파일이 있으므로 파이프라인 편집기로 파이프라인 구성의 모든 향후 변경을 수행할 수 있습니다.
사이트를 빌드하는 Job 추가#
CI/CD 파이프라인의 일반적인 작업은 프로젝트의 코드를 빌드하고 배포하는 것입니다. 사이트를 빌드하는 Job을 추가하는 것부터 시작합니다.
이 단계에서는 다음을 소개합니다:
image: 러너에게 Job을 실행할 Docker 컨테이너를 알려줍니다. 러너는:- 컨테이너 이미지를 다운로드하고 시작합니다.
- GitLab 프로젝트를 실행 중인 컨테이너에 클론합니다.
script명령을 하나씩 실행합니다.
artifacts: Job은 독립적이며 서로 리소스를 공유하지 않습니다. 하나의 Job에서 생성된 파일을 다른 Job에서 사용하려면 먼저 아티팩트로 저장해야 합니다. 그러면 이후 Job이 아티팩트를 가져와 생성된 파일을 사용할 수 있습니다.
이 단계에서 test-job을 build-job으로 교체합니다:
image를 사용하여 최신node이미지로 Job을 실행하도록 구성합니다. Docusaurus는 Node.js 프로젝트이며node이미지에는 필요한npm명령이 내장되어 있습니다.npm install을 실행하여 Docusaurus를 실행 중인node컨테이너에 설치한 다음npm run build를 실행하여 사이트를 빌드합니다.- Docusaurus는 빌드된 사이트를
build/에 저장하므로artifacts로 이 파일들을 저장합니다.
build-job:
image: node
script:
- npm install
- npm run build
artifacts:
paths:
- "build/"
파이프라인 편집기를 사용하여 이 파이프라인 구성을 기본 브랜치에 커밋하고 Job 로그를 확인합니다. 다음을 수행할 수 있습니다:
npm명령이 실행되고 사이트가 빌드되는 것을 확인합니다.- 끝에 아티팩트가 저장되는지 확인합니다.
- Job이 완료된 후 Job 로그 오른쪽의 Browse를 선택하여 아티팩트 파일의 내용을 탐색합니다.
사이트를 배포하는 Job 추가#
build-job에서 Docusaurus 사이트가 빌드되는지 확인한 후 배포하는 Job을 추가할 수 있습니다.
이 단계에서는 다음을 소개합니다:
stage와stages: 가장 일반적인 파이프라인 구성은 Job을 Stage로 그룹화합니다. 동일한 Stage의 Job은 병렬로 실행될 수 있으며, 이후 Stage의 Job은 이전 Stage의 Job이 완료될 때까지 기다립니다. Job이 실패하면 전체 Stage가 실패로 간주되고 이후 Stage의 Job은 실행을 시작하지 않습니다.- GitLab Pages: 정적 사이트를 호스팅하려면 GitLab Pages를 사용합니다.
이 단계에서:
- 빌드된 사이트를 가져와 배포하는 Job을 추가합니다. GitLab Pages를 사용할 때 Job의 이름은 항상
pages입니다.build-job의 아티팩트는 자동으로 가져와 Job에 추출됩니다. 하지만 Pages는public/디렉토리에서 사이트를 찾으므로 사이트를 해당 디렉토리로 이동하는script명령을 추가합니다. stages섹션을 추가하고 각 Job의 Stage를 정의합니다.build-job은 먼저buildStage에서 실행되고,pages는 이후deployStage에서 실행됩니다.
stages: # List of stages for jobs and their order of execution
- build
- deploy
build-job:
stage: build # Set this job to run in the `build` stage
image: node
script:
- npm install
- npm run build
artifacts:
paths:
- "build/"
pages:
stage: deploy # Set this new job to run in the `deploy` stage
script:
- mv build/ public/
artifacts:
paths:
- "public/"
파이프라인 편집기를 사용하여 이 파이프라인 구성을 기본 브랜치에 커밋하고 Pipelines 목록에서 파이프라인 세부 정보를 확인합니다. 다음을 확인합니다:
- 두 Job이 서로 다른 Stage인
build와deploy에서 실행됩니다. pagesJob이 완료된 후pages:deployJob이 나타납니다. 이는 Pages 사이트를 배포하는 GitLab 프로세스입니다. 해당 Job이 완료되면 새 Docusaurus 사이트를 방문할 수 있습니다.
사이트를 보려면:
- 왼쪽 사이드바에서 Deploy > Pages를 선택합니다.
- Use unique domain이 꺼져 있는지 확인합니다.
- Access pages 아래에서 링크를 선택합니다. URL 형식은
https://<my-username>.gitlab.io/<project-name>과 유사해야 합니다. 자세한 내용은 GitLab Pages 기본 도메인 이름을 참조하세요.
고유 도메인을 사용해야 하는 경우, docusaurus.config.js에서 baseUrl을 /로 설정합니다.
테스트 Job 추가#
사이트가 예상대로 빌드되고 배포되었으므로 이제 테스트 및 린팅을 추가할 수 있습니다. 예를 들어 Ruby 프로젝트는 RSpec 테스트 Job을 실행할 수 있습니다. Docusaurus는 Markdown과 생성된 HTML을 사용하는 정적 사이트이므로 이 튜토리얼에서는 Markdown과 HTML을 테스트하는 Job을 추가합니다.
이 단계에서는 다음을 소개합니다:
allow_failure: 간헐적으로 실패하거나 실패가 예상되는 Job은 생산성을 저하시키거나 문제 해결하기 어려울 수 있습니다.allow_failure를 사용하면 파이프라인 실행을 중단하지 않고 Job이 실패하도록 허용합니다.dependencies:dependencies를 사용하여 아티팩트를 가져올 Job을 나열함으로써 개별 Job의 아티팩트 다운로드를 제어합니다.
이 단계에서:
build와deploy사이에 실행되는 새testStage를 추가합니다. 이 세 Stage는 구성에서stages가 정의되지 않은 경우 기본 Stage입니다.- markdownlint를 실행하고 프로젝트의 Markdown을 확인하는
lint-markdownJob을 추가합니다. markdownlint는 Markdown 파일이 포맷팅 표준을 따르는지 확인하는 정적 분석 도구입니다.- Docusaurus가 생성하는 샘플 Markdown 파일은
blog/와docs/에 있습니다. - 이 도구는 원본 Markdown 파일만 스캔하며,
build-job아티팩트에 저장된 생성된 HTML이 필요하지 않습니다.dependencies: []로 Job을 빠르게 실행하여 아티팩트를 가져오지 않습니다. - 일부 샘플 Markdown 파일이 기본 markdownlint 규칙을 위반하므로 규칙 위반에도 파이프라인이 계속되도록
allow_failure: true를 추가합니다.
- Docusaurus가 생성하는 샘플 Markdown 파일은
- HTMLHint를 실행하고 생성된 HTML을 확인하는
test-htmlJob을 추가합니다. HTMLHint는 생성된 HTML에서 알려진 문제를 스캔하는 정적 분석 도구입니다. test-html과pages는 모두build-job아티팩트에 있는 생성된 HTML이 필요합니다. Job은 기본적으로 이전 Stage의 모든 Job에서 아티팩트를 가져오지만, 향후 파이프라인 변경 후 다른 아티팩트를 실수로 다운로드하지 않도록dependencies:를 추가합니다.
stages:
- build
- test # Add a `test` stage for the test jobs
- deploy
build-job:
stage: build
image: node
script:
- npm install
- npm run build
artifacts:
paths:
- "build/"
lint-markdown:
stage: test
image: node
dependencies: [] # Don't fetch any artifacts
script:
- npm install markdownlint-cli2 --global # Install markdownlint into the container
- markdownlint-cli2 -v # Verify the version, useful for troubleshooting
- markdownlint-cli2 "blog/**/*.md" "docs/**/*.md" # Lint all markdown files in blog/ and docs/
allow_failure: true # This job fails right now, but don't let it stop the pipeline.
test-html:
stage: test
image: node
dependencies:
- build-job # Only fetch artifacts from `build-job`
script:
- npm install --save-dev htmlhint # Install HTMLHint into the container
- npx htmlhint --version # Verify the version, useful for troubleshooting
- npx htmlhint build/ # Lint all markdown files in blog/ and docs/
pages:
stage: deploy
dependencies:
- build-job # Only fetch artifacts from `build-job`
script:
- mv build/ public/
artifacts:
paths:
- "public/"
이 파이프라인 구성을 기본 브랜치에 커밋하고 파이프라인 세부 정보를 확인합니다.
lint-markdownJob은 샘플 Markdown이 기본 markdownlint 규칙을 위반하기 때문에 실패하지만 실패가 허용됩니다. 다음을 수행할 수 있습니다:- 지금은 위반을 무시합니다. 튜토리얼의 일부로 수정할 필요가 없습니다.
- Markdown 파일 위반을 수정합니다. 그런 다음
allow_failure를false로 변경하거나allow_failure를 완전히 제거할 수 있습니다. 정의되지 않은 경우allow_failure: false가 기본 동작입니다. - markdownlint 구성 파일을 추가하여 경고할 규칙 위반을 제한합니다.
- Markdown 파일 내용을 변경하고 다음 배포 후 사이트에서 변경 사항을 확인할 수도 있습니다.
머지 리퀘스트 파이프라인 사용 시작#
이전 파이프라인 구성에서는 파이프라인이 성공적으로 완료될 때마다 사이트가 배포되지만, 이는 이상적인 개발 워크플로가 아닙니다. 피처 브랜치와 머지 리퀘스트에서 작업하고 변경 사항이 기본 브랜치에 머지될 때만 사이트를 배포하는 것이 더 좋습니다.
이 단계에서는 다음을 소개합니다:
rules: 각 Job에 규칙을 추가하여 어떤 파이프라인에서 실행될지 구성합니다. 머지 리퀘스트 파이프라인, 예약된 파이프라인 또는 기타 특정 상황에서 실행되도록 Job을 구성할 수 있습니다. 규칙은 위에서 아래로 평가되며, 규칙이 일치하면 Job이 파이프라인에 추가됩니다.- CI/CD 변수: 이 환경 변수를 사용하여 구성 파일과 스크립트 명령에서 Job 동작을 구성합니다.
사전 정의된 CI/CD 변수는 수동으로 정의할 필요가 없는 변수입니다. 파이프라인에 자동으로 삽입되므로 파이프라인을 구성하는 데 사용할 수 있습니다. 변수는 일반적으로
$VARIABLE_NAME형식으로 지정됩니다. 사전 정의된 변수는 일반적으로$CI_로 시작합니다.
이 단계에서:
- 새 피처 브랜치를 만들고 기본 브랜치 대신 브랜치에서 변경합니다.
- 각 Job에
rules를 추가합니다:- 사이트는 기본 브랜치에 대한 변경 사항에 대해서만 배포되어야 합니다.
- 다른 Job은 머지 리퀘스트 또는 기본 브랜치의 모든 변경 사항에 대해 실행되어야 합니다.
- 이 파이프라인 구성으로 Job을 실행하지 않고 피처 브랜치에서 작업할 수 있어 리소스를 절약합니다. 변경 사항의 유효성을 검사할 준비가 되면 머지 리퀘스트를 만들고 머지 리퀘스트에서 실행되도록 구성된 Job으로 파이프라인이 실행됩니다.
- 머지 리퀘스트가 수락되어 변경 사항이 기본 브랜치에 머지되면
pages배포 Job도 포함된 새 파이프라인이 실행됩니다. Job이 실패하지 않으면 사이트가 배포됩니다.
stages:
- build
- test
- deploy
build-job:
stage: build
image: node
script:
- npm install
- npm run build
artifacts:
paths:
- "build/"
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event' # Run for all changes to a merge request's source branch
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run for all changes to the default branch
lint-markdown:
stage: test
image: node
dependencies: []
script:
- npm install markdownlint-cli2 --global
- markdownlint-cli2 -v
- markdownlint-cli2 "blog/**/*.md" "docs/**/*.md"
allow_failure: true
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event' # Run for all changes to a merge request's source branch
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run for all changes to the default branch
test-html:
stage: test
image: node
dependencies:
- build-job
script:
- npm install --save-dev htmlhint
- npx htmlhint --version
- npx htmlhint build/
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event' # Run for all changes to a merge request's source branch
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run for all changes to the default branch
pages:
stage: deploy
dependencies:
- build-job
script:
- mv build/ public/
artifacts:
paths:
- "public/"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run for all changes to the default branch only
머지 리퀘스트의 변경 사항을 머지합니다. 이 작업은 기본 브랜치를 업데이트합니다. 새 파이프라인에 사이트를 배포하는 pages Job이 포함되어 있는지 확인합니다.
앞으로 파이프라인 구성에 대한 모든 변경 사항에는 피처 브랜치와 머지 리퀘스트를 사용해야 합니다. Git 태그 생성이나 파이프라인 스케줄 추가와 같은 다른 프로젝트 변경 사항은 해당 경우에 대한 규칙을 추가하지 않는 한 파이프라인을 트리거하지 않습니다.
중복 구성 줄이기#
이제 파이프라인에 동일한 rules와 image 구성을 가진 세 개의 Job이 있습니다.
이 규칙을 반복하는 대신 extends와 default를 사용하여 단일 진실 공급원을 만듭니다.
이 단계에서는 다음을 소개합니다:
- 숨겨진 Job:
.으로 시작하는 Job은 파이프라인에 추가되지 않습니다. 재사용하려는 구성을 보관하는 데 사용합니다. extends: 종종 숨겨진 Job에서 여러 곳에서 구성을 반복하는 데 extends를 사용합니다. 숨겨진 Job의 구성을 업데이트하면 해당 숨겨진 Job을 상속하는 모든 Job이 업데이트된 구성을 사용합니다.default: 정의되지 않은 경우 모든 Job에 적용되는 키워드 기본값을 설정합니다.- YAML 재정의:
extends또는default로 구성을 재사용할 때 Job에서 명시적으로 키워드를 정의하여extends또는default구성을 재정의할 수 있습니다.
이 단계에서:
build-job,lint-markdown,test-html에서 반복되는 규칙을 보관하는.standard-rules숨겨진 Job을 추가합니다.extends를 사용하여 세 Job에서.standard-rules구성을 재사용합니다.image기본값을node로 정의하는default섹션을 추가합니다.pages배포 Job에는 기본node이미지가 필요하지 않으므로 매우 작고 빠른 이미지인busybox를 명시적으로 사용합니다.
stages:
- build
- test
- deploy
default: # Add a default section to define the `image` keyword's default value
image: node
.standard-rules: # Make a hidden job to hold the common rules
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
build-job:
extends:
- .standard-rules # Reuse the configuration in `.standard-rules` here
stage: build
script:
- npm install
- npm run build
artifacts:
paths:
- "build/"
lint-markdown:
stage: test
extends:
- .standard-rules # Reuse the configuration in `.standard-rules` here
dependencies: []
script:
- npm install markdownlint-cli2 --global
- markdownlint-cli2 -v
- markdownlint-cli2 "blog/**/*.md" "docs/**/*.md"
allow_failure: true
test-html:
stage: test
extends:
- .standard-rules # Reuse the configuration in `.standard-rules` here
dependencies:
- build-job
script:
- npm install --save-dev htmlhint
- npx htmlhint --version
- npx htmlhint build/
pages:
stage: deploy
image: busybox # Override the default `image` value with `busybox`
dependencies:
- build-job
script:
- mv build/ public/
artifacts:
paths:
- "public/"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
머지 리퀘스트를 사용하여 이 파이프라인 구성을 기본 브랜치에 커밋합니다. 파일은 더 단순하지만 이전 단계와 동일한 동작을 해야 합니다.
전체 파이프라인을 만들고 더 효율적으로 간소화했습니다. 수고하셨습니다!
이제 이 지식을 바탕으로 CI/CD YAML 구문 참조에서 나머지 .gitlab-ci.yml 키워드에 대해 알아보고 자신만의 파이프라인을 구축할 수 있습니다.
