자습서: 복잡한 파이프라인 만들기

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated

이 자습서는 점진적으로 더 복잡한 CI/CD 파이프라인을 구성하는 방법을 안내합니다.

파이프라인은 항상 완전히 작동하지만 각 단계에서 더 많은 기능을 갖추게 됩니다.

목표는 문서화 사이트를 빌드, 테스트 및 배포하는 것입니다.

이 자습서를 완료하면 GitLab.com에 새로운 프로젝트와 Docusaurus를 사용하는 작동하는 문서화 사이트가 생깁니다.

이 자습서를 완료하려면 다음을 수행해야 합니다:

  1. Docusaurus 파일을 보관할 프로젝트 생성
  2. 초기 파이프라인 구성 파일 만들기
  3. 사이트 빌드를 위한 작업 추가
  4. 사이트 배포를 위한 작업 추가
  5. 테스트 작업 추가
  6. 병합 요청 파이프라인 사용 시작
  7. 중복된 구성 줄이기

필수 조건

  • GitLab.com에 계정이 필요합니다.
  • Git에 익숙해야 합니다.
  • Node.js가 로컬 머신에 설치되어 있어야 합니다. 예를 들어, macOS에서는 brew install nodenode 설치할 수 있습니다.

Docusaurus 파일을 보관할 프로젝트 만들기

파이프라인 구성을 추가하기 전에 먼저 GitLab.com에 Docusaurus 프로젝트를 설정해야 합니다:

  1. 사용자 이름 아래에 새 프로젝트를 만드세요(그룹이 아님):
    1. 왼쪽 사이드바에서 맨 위에 있는 Create new ( )를 선택하고 New project/repository를 선택합니다.
    2. Create blank project를 선택합니다.
    3. 프로젝트 세부정보를 입력합니다:
      • Project name 필드에 프로젝트 이름을 입력하세요. 예: My Pipeline Tutorial Project.
      • Initialize repository with a README를 선택합니다.
    4. Create project를 선택합니다.
  2. 프로젝트 개요 페이지에서 오른쪽 상단의 Code를 선택하여 프로젝트의 클론 경로를 찾습니다. SSH 또는 HTTP 경로를 복사하여 해당 경로를 사용하여 프로젝트를 로컬로 클론합니다.

    예를 들어, SSH로 pipeline-tutorial 디렉토리에 클론하려면:

    git clone git@gitlab.com:my-username/my-pipeline-tutorial-project.git pipeline-tutorial  
    
  3. 프로젝트 디렉토리로 변경한 후 새로운 Docusaurus 사이트를 생성합니다:

    cd pipeline-tutorial  
    npm init docusaurus  
    

    Docusaurus 초기화 마법사가 사이트에 관한 질문을 합니다. 모든 기본 옵션을 사용하세요.

  4. 초기화 마법사는 website/에 사이트를 설정하지만, 사이트는 프로젝트 루트에 있어야 합니다. 파일을 루트로 이동하고 이전 디렉토리를 삭제하세요:

    mv website/* .  
    rm -r website  
    
  5. Docusaurus 구성 파일을 GitLab 프로젝트의 세부정보로 업데이트합니다. docusaurus.config.js에서:

    • url: 을 다음 형식의 경로로 설정합니다: https://<my-username>.gitlab.io/.
    • baseUrl: 을 프로젝트 이름으로 설정합니다, 예: /my-pipeline-tutorial-project/.
  6. 변경 내용을 커밋하고 GitLab에 푸시합니다:

    git add .  
    git commit -m "Add simple generated Docusaurus site"  
    git push origin  
    

초기 CI/CD 구성 파일 생성

프로젝트에서 CI/CD가 활성화되고 작업을 실행할 수 있는 러너가 사용 가능하도록 가장 간단한 파이프라인 구성 파일부터 시작합니다.

이 단계에서는 다음을 소개합니다:

  • Jobs: 이는 명령을 실행하는 파이프라인의 독립적인 부분입니다. Jobs는 GitLab 인스턴스와 분리된 runners에서 실행됩니다.
  • script: 작업 구성의 이 섹션은 작업의 명령을 정의하는 곳입니다. 여러 개의 명령이 있을 경우(배열의 경우), 이들은 순서대로 실행됩니다. 각 명령은 CLI 명령으로 실행된 것처럼 실행됩니다. 기본적으로, 명령이 실패하거나 오류를 반환하면 작업은 실패로 플래그가 설정되고 더 이상 명령이 실행되지 않습니다.

이 단계에서는 다음과 같은 구성을 가진 .gitlab-ci.yml 파일을 프로젝트의 루트에 생성합니다:

test-job:
  script:
    - echo "This is my first job!"
    - date

이 변경 사항을 GitLab에 커밋하고 푸시한 후에:

  1. Build > Pipelines로 이동하여 단일 작업으로 GitLab에서 파이프라인이 실행되는지 확인하세요.
  2. 파이프라인을 선택한 후, 작업을 선택하여 작업 로그를 보고 This is my first job! 메시지와 날짜를 확인하세요.

이제 프로젝트에 .gitlab-ci.yml 파일이 있으므로, 파이프라인 편집기를 사용하여 모든 향후 파이프라인 구성 변경을 할 수 있습니다.

사이트를 빌드하는 작업 추가

CI/CD 파이프라인의 일반적인 작업은 프로젝트의 코드를 빌드한 다음 배포하는 것입니다. 사이트를 빌드하는 작업을 추가하여 시작합니다.

이 단계에서는 다음을 소개합니다:

  • image: 작업을 실행하는 데 사용할 Docker 컨테이너를 러너에 지정합니다. 러너는:
    1. 컨테이너 이미지를 다운로드하고 시작합니다.
    2. 실행 중인 컨테이너에 GitLab 프로젝트를 클론합니다.
    3. script 명령을 하나씩 실행합니다.
  • artifacts: Jobs는 독립적이며 서로 자원을 공유하지 않습니다. 하나의 작업에서 생성된 파일을 다른 작업에서 사용하려면 먼저 이를 artifacts로 저장해야 합니다. 그런 다음 나중의 작업에서 artifacts를 검색하여 생성된 파일을 사용할 수 있습니다.

이 단계에서는 test-jobbuild-job으로 변경합니다:

  • 최신 node 이미지를 사용하여 작업 구성을 설정합니다. Docusaurus 는 Node.js 프로젝트이며 node 이미지에는 필요한 npm 명령이 내장되어 있습니다.
  • npm install을 실행하여 실행 중인 node 컨테이너에 Docusaurus를 설치하고, 그런 다음 npm run build를 실행하여 사이트를 빌드합니다.
  • Docusaurus는 빌드된 사이트를 build/에 저장하므로 이 파일들을 artifacts로 저장합니다.
build-job:
  image: node
  script:
    - npm install
    - npm run build
  artifacts:
    paths:
      - "build/"

파이프라인 편집기를 사용하여 이 파이프라인 구성을 기본 분기로 커밋하고 작업 로그를 확인합니다. 다음을 수행할 수 있습니다:

  • npm 명령이 실행되고 사이트를 빌드하는 것을 확인하세요.
  • 마지막에 artifacts가 저장되었는지 확인하세요.
  • 작업이 완료된 후 작업 로그 오른쪽에 있는 Browse를 선택하여 artifacts 파일의 내용을 탐색하세요.

사이트를 배포하는 작업 추가하기

build-job에서 Docusaurus 사이트가 빌드되는 것을 확인한 후, 이를 배포하는 작업을 추가할 수 있습니다.

이 단계에서는 다음을 소개합니다:

  • stagestages: 가장 일반적인 파이프라인 구성은 작업을 단계로 그룹화합니다. 같은 단계의 작업은 병렬로 실행될 수 있으며, 이후 단계의 작업은 이전 단계의 작업이 완료될 때까지 대기합니다. 작업이 실패하면 전체 단계는 실패로 간주되며, 이후 단계의 작업은 실행되지 않습니다.
  • GitLab Pages: 정적 사이트를 호스팅하기 위해 GitLab Pages를 사용합니다.

이 단계에서는:

  • 빌드된 사이트를 가져와 배포하는 작업을 추가합니다. GitLab Pages를 사용할 때, 이 작업의 이름은 항상 pages입니다. build-job에서 생성된 아티팩트는 자동으로 가져와서 작업으로 추출됩니다. 하지만 Pages는 public/ 디렉토리에서 사이트를 찾기 때문에, 그 디렉토리로 사이트를 이동하는 script 명령을 추가하세요.
  • stages 섹션을 추가하고 각 작업의 단계를 정의합니다. build-jobbuild 단계에서 먼저 실행되고, pages는 이후 deploy 단계에서 실행됩니다.
stages:          # 작업과 실행 순서의 단계 목록
  - build
  - deploy

build-job:
  stage: build   # 이 작업이 `build` 단계에서 실행되도록 설정
  image: node
  script:
    - npm install
    - npm run build
  artifacts:
    paths:
      - "build/"

pages:
  stage: deploy  # 이 새로운 작업이 `deploy` 단계에서 실행되도록 설정
  script:
    - mv build/ public/
  artifacts:
    paths:
      - "public/"

파이프라인 편집기를 사용하여 이 파이프라인 구성을 기본 브랜치에 커밋하고, 파이프라인 목록에서 파이프라인 세부정보를 확인하세요. 다음을 확인하세요:

  • 두 작업이 서로 다른 단계, 즉 builddeploy에서 실행됩니다.
  • pages 작업이 완료된 후 pages:deploy 작업이 나타납니다. 이는 Pages 사이트를 배포하는 GitLab 프로세스입니다. 해당 작업이 완료되면 새로운 Docusaurus 사이트를 방문할 수 있습니다.

사이트를 보려면:

  • 왼쪽 사이드바에서 Deploy > Pages를 선택합니다.
  • Use unique domain이 꺼져 있는지 확인합니다.
  • Access pages에서 링크를 선택합니다. URL 형식은 다음과 유사해야 합니다: https://<my-username>.gitlab.io/<project-name>. 더 많은 정보는 GitLab Pages 기본 도메인 이름을 참조하세요.

참고: 개별 도메인을 사용해야 하는 경우, docusaurus.config.js에서 baseUrl:을 /로 설정하세요.

테스트 작업 추가하기

이제 사이트가 예상대로 빌드되고 배포되므로, 테스트와 린트를 추가할 수 있습니다.

예를 들어, Ruby 프로젝트는 RSpec 테스트 작업을 실행할 수 있습니다.

Docusaurus는 Markdown과 생성된 HTML을 사용하는 정적 사이트이므로, 이 튜토리얼에서는 Markdown과 HTML을 테스트하기 위한 작업을 추가합니다.

이 단계에서는 다음을 소개합니다:

  • allow_failure: 간헐적으로 실패하거나 예상대로 실패하는 작업은 생산성을 저하시키거나 문제 해결을 어렵게 만들 수 있습니다. allow_failure를 사용하여 파이프라인 실행을 중단하지 않고 작업이 실패하도록 허용합니다.
  • dependencies: dependencies를 사용하여 어떤 작업에서 아티팩트를 가져올지 목록을 나열하여 개별 작업의 아티팩트 다운로드를 제어합니다.

이 단계에서는:

  • builddeploy 사이에 새로운 test 단계를 추가합니다. 이 세 단계는 구성에서 stages가 정의되지 않은 경우 기본 단계입니다.
  • markdownlint를 실행하는 lint-markdown 작업을 추가하여 프로젝트의 Markdown을 검사합니다. markdownlint는 Markdown 파일이 포맷팅 기준을 준수하는지 확인하는 정적 분석 도구입니다.
    • Docusaurus에서 생성된 샘플 Markdown 파일은 blog/docs/에 있습니다.
    • 이 도구는 원본 Markdown 파일만 스캔하며, build-job 아티팩트에 저장된 생성된 HTML은 필요하지 않습니다. dependencies: []로 작업의 속도를 높여 아티팩트를 가져오지 않도록 설정합니다.
    • 샘플 Markdown 파일 중 일부가 기본 markdownlint 규칙을 위반하므로, 파이프라인이 계속 진행될 수 있도록 allow_failure: true를 추가합니다.
  • HTMLHint를 실행하여 생성된 HTML을 검사하는 test-html 작업을 추가합니다. HTMLHint는 생성된 HTML에서 알려진 문제를 스캔하는 정적 분석 도구입니다.
  • test-htmlpages 작업 모두 build-job 아티팩트에서 생성된 HTML이 필요합니다. 기본적으로 작업은 이전 단계의 모든 작업에서 아티팩트를 가져오지만, 미래의 파이프라인 변경 후 작업이 우연히 다른 아티팩트를 다운로드하지 않도록 dependencies:를 추가합니다.
stages:
  - build
  - test               # 테스트 작업을 위한 `test` 단계를 추가
  - deploy

build-job:
  stage: build
  image: node
  script:
    - npm install
    - npm run build
  artifacts:
    paths:
      - "build/"

lint-markdown:
  stage: test
  image: node
  dependencies: []     # 아티팩트를 가져오지 않도록 설정
  script:
    - npm install markdownlint-cli2 --global           # markdownlint를 컨테이너에 설치
    - markdownlint-cli2 -v                             # 버전을 확인하여 문제 해결에 유용
    - markdownlint-cli2 "blog/**/*.md" "docs/**/*.md"  # blog/ 및 docs/에서 모든 Markdown 파일 검사
  allow_failure: true  # 이 작업은 현재 실패하지만 파이프라인을 중단하지 않도록 설정합니다.

test-html:
  stage: test
  image: node
  dependencies:
    - build-job        # `build-job`에서만 아티팩트를 가져옵니다.
  script:
    - npm install --save-dev htmlhint                  # HTMLHint를 컨테이너에 설치
    - npx htmlhint --version                           # 버전을 확인하여 문제 해결에 유용
    - npx htmlhint build/                              # blog/ 및 docs/의 모든 Markdown 파일 검사

pages:
  stage: deploy
  dependencies:
    - build-job        # `build-job`에서만 아티팩트를 가져옵니다.
  script:
    - mv build/ public/
  artifacts:
    paths:
      - "public/"

이 파이프라인 구성을 기본 브랜치에 커밋하고, 파이프라인 세부정보를 확인하세요.

  • lint-markdown 작업이 기본 markdownlint 규칙을 위반하여 실패하지만, 실패를 허용하도록 설정되어 있습니다. 다음을 수행할 수 있습니다:
    • 지금은 위반 사항을 무시하세요. 이는 튜토리얼의 일환으로 수정할 필요는 없습니다.
    • Markdown 파일의 위반 사항을 수정하세요. 그런 다음 allow_failurefalse로 변경하거나 allow_failure를 완전히 제거할 수 있습니다. 정의되지 않았을 때의 기본 동작이 allow_failure: false입니다.
    • 어떤 규칙 위반을 알릴지 제한하기 위해 markdownlint 구성 파일을 추가하세요.
  • Markdown 파일 콘텐츠에 대한 변경을 하고, 다음 배포 후 사이트에서 변경 사항을 확인할 수도 있습니다.

병합 요청 파이프라인 사용 시작

위의 파이프라인 구성에 따라, 파이프라인이 성공적으로 완료될 때마다 사이트가 배포되지만, 이는 이상적인 개발 워크플로우가 아닙니다. 기능 브랜치와 병합 요청에서 작업하는 것이 더 좋으며, 변경 사항이 기본 브랜치에 병합될 때만 사이트를 배포해야 합니다.

이 단계에서는 다음을 소개합니다:

  • rules: 각 작업에 규칙을 추가하여 어떤 파이프라인에서 실행되는지 구성할 수 있습니다. 병합 요청 파이프라인(merge request pipelines), 예약된 파이프라인(scheduled pipelines), 또는 다른 특정 상황에서 작업이 실행되도록 구성할 수 있습니다. 규칙은 위에서 아래로 평가되며, 규칙이 일치하면 작업이 파이프라인에 추가됩니다.

  • CI/CD variables: 이 환경 변수를 사용하여 구성 파일 및 스크립트 명령에서 작업의 동작을 구성합니다. 미리 정의된 CI/CD 변수는 수동으로 정의할 필요가 없는 변수입니다. 이들은 파이프라인에 자동으로 주입되어 파이프라인을 구성하는 데 사용할 수 있습니다. 변수는 일반적으로 $VARIABLE_NAME 형식으로 나타내며, 미리 정의된 변수는 일반적으로 $CI_로 시작합니다.

이 단계에서는:

  • 새로운 기능 브랜치를 생성하고 기본 브랜치 대신 해당 브랜치에서 변경 작업을 수행합니다.

  • 각 작업에 rules 추가:
    • 사이트는 기본 브랜치에 대한 변경의 경우에만 배포해야 합니다.
    • 다른 작업은 병합 요청 또는 기본 브랜치의 모든 변경에 대해 실행되어야 합니다.
  • 이 파이프라인 구성으로, 작업을 실행하지 않고 기능 브랜치에서 작업할 수 있어 리소스를 절약할 수 있습니다. 변경 사항을 검증할 준비가 되면, 병합 요청을 생성하고 병합 요청에서 실행되도록 구성된 작업이 포함된 파이프라인이 실행됩니다.

  • 병합 요청이 수락되고 변경 사항이 기본 브랜치에 병합되면, pages 배포 작업도 포함된 새로운 파이프라인이 실행됩니다. 모든 작업이 실패하지 않으면 사이트가 배포됩니다.
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'  # 병합 요청의 소스 브랜치에 대한 모든 변경에 대해 실행
    - if: $CI_COMMIT_BRANCH == $CI_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'  # 병합 요청의 소스 브랜치에 대한 모든 변경에 대해 실행
    - if: $CI_COMMIT_BRANCH == $CI_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'  # 병합 요청의 소스 브랜치에 대한 모든 변경에 대해 실행
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH       # 기본 브랜치에 대한 모든 변경에 대해 실행

pages:
  stage: deploy
  dependencies:
    - build-job
  script:
    - mv build/ public/
  artifacts:
    paths:
      - "public/"
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH      # 기본 브랜치에 대한 모든 변경에 대해 실행

병합 요청에서 변경 사항을 병합합니다. 이 작업은 기본 브랜치를 업데이트합니다. 새로운 파이프라인에 사이트를 배포하는 pages 작업이 포함되어 있는지 확인합니다.

향후 파이프라인 구성에 대한 모든 변경 사항에 대해 기능 브랜치와 병합 요청을 사용해야 합니다. Git 태그를 생성하거나 파이프라인 일정을 추가하는 것과 같은 다른 프로젝트 변경은 이러한 경우에 대한 규칙을 추가하지 않는 한 파이프라인을 트리거하지 않습니다.

중복된 구성 줄이기

파이프라인에는 이제 동일한 rulesimage 구성을 가진 세 개의 작업이 포함되어 있습니다. 이러한 규칙을 반복하는 대신 extendsdefault를 사용하여 단일 진실의 소스를 만듭니다.

이 단계에서는 다음을 소개합니다:

  • 숨겨진 작업: .로 시작하는 작업은 파이프라인에 추가되지 않습니다. 재사용하고 싶은 구성을 보관하는 데 사용하세요.
  • extends: extends를 사용하여 숨겨진 작업에서 여러 위치에서 구성을 반복합니다. 숨겨진 작업의 구성을 업데이트하면, 숨겨진 작업을 확장하는 모든 작업이 업데이트된 구성을 사용합니다.
  • default: 정의되지 않은 경우 모든 작업에 적용되는 키워드 기본값을 설정합니다.
  • YAML 재정의: extends 또는 default로 구성을 재사용할 때, 작업 내에서 키워드를 명시적으로 정의하여 extends 또는 default 구성을 재정의할 수 있습니다.

이 단계에서는:

  • .standard-rules라는 숨겨진 작업을 추가하여 build-job, lint-markdown, test-html에서 반복되는 규칙을 보관합니다.

  • extends를 사용하여 세 개의 작업에서 .standard-rules 구성을 재사용합니다.

  • 이미지 기본값을 node로 정의하기 위해 default 섹션을 추가합니다.

  • pages 배포 작업은 기본 node 이미지를 필요로 하지 않으므로, 매우 작고 빠른 이미지인 busybox를 명시적으로 사용합니다.

stages:
  - build
  - test
  - deploy

default:               # `image` 키워드의 기본값을 정의하는 기본 섹션 추가
  image: node

.standard-rules:       # 공통 규칙을 보관하기 위한 숨겨진 작업 만들기
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

build-job:
  extends:
    - .standard-rules  # 여기서 `.standard-rules`의 구성을 재사용
  stage: build
  script:
    - npm install
    - npm run build
  artifacts:
    paths:
      - "build/"

lint-markdown:
  stage: test
  extends:
    - .standard-rules  # 여기서 `.standard-rules`의 구성을 재사용
  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  # 여기서 `.standard-rules`의 구성을 재사용
  dependencies:
    - build-job
  script:
    - npm install --save-dev htmlhint
    - npx htmlhint --version
    - npx htmlhint build/

pages:
  stage: deploy
  image: busybox       # `image` 기본값을 `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 키워드에 대해 배우고 자신만의 파이프라인을 만드세요.