튜토리얼: 복잡한 파이프라인 생성

이 튜토리얼은 단계별로 점진적으로 복잡한 CI/CD 파이프라인을 구성하는 방법을 안내합니다. 파이프라인은 항상 완전히 기능하며 각 단계마다 더 많은 기능을 얻습니다. 목표는 문서 사이트를 빌드, 테스트 및 배포하는 것입니다.

이 튜토리얼을 완료하면 GitLab.com에 새 프로젝트가 생성되고 Docusaurus를 사용하여 작동하는 문서 사이트가 구축됩니다.

이 튜토리얼을 완료하려면 다음을 수행해야 합니다:

  1. Docusaurus 파일을 보유할 프로젝트를 생성합니다.
  2. 초기 파이프라인 구성 파일을 생성합니다.
  3. 사이트를 빌드하는 작업을 추가합니다.
  4. 사이트를 배포하는 작업을 추가합니다.
  5. 테스트 작업을 추가합니다.
  6. Merge Request 파이프라인 사용을 시작합니다.
  7. 중복된 구성을 줄입니다.

사전 요구 사항

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

Docusaurus 파일을 보유할 프로젝트 생성

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

  1. 사용자 이름(그룹이 아님) 아래에 새 프로젝트를 생성합니다:
    1. 왼쪽 사이드바에서 검색 또는 이동을 선택합니다.
    2. 내 모든 프로젝트 보기를 선택합니다.
    3. 페이지 오른쪽에서 새 프로젝트를 선택합니다.
    4. 빈 프로젝트 만들기를 선택합니다.
    5. 프로젝트 세부 정보를 입력합니다:
      • 프로젝트 이름 필드에 프로젝트 이름(예: 나의 파이프라인 튜토리얼 프로젝트)을 입력합니다.
      • README 파일로 리포지터리 초기화를 선택합니다.
    6. 프로젝트 만들기를 선택합니다.
  2. 프로젝트 개요 페이지에서 오른쪽 상단에서 코드를 선택하여 프로젝트의 복제 경로를 찾습니다. SSH 또는 HTTP 경로를 복사하고 해당 경로를 사용하여 프로젝트를 로컬로 복제합니다.

    예를 들어, 컴퓨터의 pipeline-tutorial 디렉터리에 SSH로 복제하려면:

    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 "간단하게 생성된 Docusaurus 사이트 추가"
    git push origin
    

초기 CI/CD 구성 파일 생성

프로젝트의 가장 간단한 파이프라인 구성 파일부터 시작하여 CI/CD가 활성화되고 작업을 실행할 수 있는 러너가 사용 가능한지 확인하세요.

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

  • 작업: 파이프라인의 자체 모듈화된 부분으로 명령을 실행합니다. 작업은 러너에서 실행됩니다. 이 러너는 GitLab 인스턴스와 별도입니다.
  • script: 작업 구성의 이 부분은 작업의 명령을 정의하는 곳입니다. 여러 개의 명령이 있는 경우(배열 형태), 순서대로 실행됩니다. 각 명령은 CLI 명령으로 실행됩니다. 기본적으로 명령이 실패하거나 오류가 발생하면 작업이 실패로 표시되고 더 이상 명령이 실행되지 않습니다.

이 단계에서 프로젝트의 루트에 .gitlab-ci.yml 파일을 다음 구성으로 생성합니다:

test-job:
  script:
    - echo "첫 번째 작업입니다!"
    - date

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

  1. 빌드 > 파이프라인으로 이동하여 GitLab에서 이 단일 작업을 실행하는 파이프라인이 있는지 확인합니다.
  2. 파이프라인을 선택한 후 작업을 선택하여 작업의 로그를 보고 첫 번째 작업입니다! 메시지 다음에 날짜가 표시되는지 확인합니다.

프로젝트에 .gitlab-ci.yml 파일이 포함되어 있으므로 모든 후속 변경은 파이프라인 편집기를 사용하여 파이프라인 구성을 수행할 수 있습니다.

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

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

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

  • image: 러너에게 작업을 실행할 Docker 컨테이너를 알려줍니다. 러너는 컨테이너 이미지를 다운로드하고 시작합니다. GitLab 프로젝트를 실행 중인 컨테이너에 복제합니다. 그런 다음 script 명령을 하나씩 실행합니다.
  • artifacts: 작업은 서로의 리소스를 공유하지 않으며, 한 작업에서 생성된 파일을 다른 작업에서 사용하려면 먼저 이를 artifacts로 저장해야 합니다. 그런 다음 후속 작업이 artifacts를 검색하고 생성된 파일을 사용할 수 있습니다.

이 단계에서 test-jobbuild-job으로 교체합니다:

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

이 파이프라인 구성을 기본 브랜치에 커밋하고 작업 로그를 확인합니다. 다음을 수행할 수 있습니다:

  • npm 명령이 실행되고 사이트가 빌드되는지 확인합니다.
  • 마지막에 artifacts가 저장되는지 확인합니다.
  • 작업이 완료된 후 작업 로그 오른쪽의 찾아보기를 선택하여 artifacts 파일 내용을 확인합니다.

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

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

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

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

이 단계에서 다음을 수행합니다:

  • 빌드된 사이트를 가져오고 해당 사이트를 배포하는 작업을 추가합니다. GitLab Pages를 사용할 때 작업은 항상 pages로 명명됩니다. build-job에서 생성된 artifacts가 자동으로 가져와져서 작업에 추출됩니다. 그러나 Pages는 사이트를 항상 public/ 디렉터리에서 찾으므로 사이트를 해당 디렉터리로 이동하는 script 명령을 추가합니다.
  • stages 섹션을 추가하고 각 작업에 대한 stage를 정의합니다. build-jobbuild stage에서 먼저 실행되고, pagesdeploy stage에서 실행됩니다.
stages:          # 작업에 대한 stage 디렉터리 및 실행 순서
  - build
  - deploy

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

pages:
  stage: deploy  # 이 새 작업을 `deploy` stage에서 실행하도록 설정
  script:
    - mv build/ public/
  artifacts:
    paths:
      - "public/"

파이프라인 편집기를 사용하여이 파이프라인 구성을 기본 브랜치에 커밋하고 파이프라인 디렉터리에서 파이프라인 세부 정보를 확인합니다. 다음을 확인하세요:

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

사이트를 보려면:

  • 왼쪽 사이드바에서 배포 > Pages를 선택합니다.
  • 고유 도메인 사용을 끈 상태인지 확인합니다.
  • 페이지 액세스에서 링크를 선택합니다. URL 형식은 https://<my-username>.gitlab.io/<project-name>와 유사해야 합니다. 자세한 내용은 GitLab Pages 기본 도메인 이름을 참조하세요.
note
고유 도메인을 사용해야 하는 경우에는 docusaurus.config.js에서 baseUrl:을 /로 설정합니다.

테스트 작업 추가

이제 사이트가 기대한 대로 빌드되고 배포되기 때문에 테스트와 린팅을 추가할 수 있습니다. 예를 들어 루비 프로젝트는 RSpec 테스트 작업을 실행할 수 있습니다. Docusaurus는 Markdown과 생성된 HTML을 사용하는 정적 사이트로, 이 튜토리얼에서는 Markdown 및 HTML을 테스트할 작업을 추가합니다.

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

  • allow_failure: 때때로 실패하는 작업이나 예상대로 실패하는 작업은 프로덕션성을 떨어뜨리거나 문제 해결이 어려울 수 있습니다. allow_failure를 사용하여 작업을 실패시키지 않고 파이프라인 실행을 중단시키지 않도록 합니다.
  • dependencies: dependencies를 사용하여 개별 작업에서 아티팩트 다운로드를 제어합니다. 가져올 아티팩트 디렉터리을 나열하여 개별 작업에서 아티팩트를 가져올 수 있습니다.

이 단계에서:

  • builddeploy 사이에 실행되는 새로운 test 단계를 추가합니다. 이 3가지 단계는 설정 구성에서 stages가 정의되지 않은 경우의 기본 단계입니다.
  • lint-markdown 작업을 추가하여 markdownlint을 실행하고 프로젝트의 Markdown을 확인합니다. markdownlint는 Markdown 파일이 포맷 규칙을 따르는지 확인하는 정적 분석 도구입니다.
    • Docusaurus에서 생성하는 샘플 Markdown 파일은 blog/docs/에 있습니다.
    • 이 도구는 생성된 HTML이 build-job 아티팩트에 저장되지 않아도 원본 Markdown 파일만을 스캔합니다. 아티팩트를 가져오지 않도록 dependencies: []를 사용하여 작업을 가속화합니다.
    • 일부 샘플 Markdown 파일이 기본 markdownlint 규칙을 위반하기 때문에 allow_failure: true를 추가하여 규칙 위반에도 파이프라인이 계속될 수 있도록 합니다.
  • test-html 작업을 추가하여 HTMLHint를 실행하고 생성된 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 작업은 샘플 Markdown이 기본 markdownlint 규칙을 위반하기 때문에 실패합니다. 그러나 규칙 위반을 허용합니다. 이때, 다음을 할 수 있습니다:
    • 일단 위반 사항을 무시할 수 있습니다. 이것은 튜토리얼의 일부로 고쳐야 할 필요가 없습니다.
    • Markdown 파일 위반을 수정할 수 있습니다. 그런 다음 allow_failurefalse로 변경하거나, allow_failure: false가 정의되지 않은 경우 기본 동작이기 때문에 allow_failure를 완전히 제거할 수 있습니다.
    • markdownlint 구성 파일을 추가하여 알림을 받을 규칙 위반을 제한할 수 있습니다.
  • 또한 Markdown 파일 콘텐츠를 변경하고 변경 내용이 다음 배포 후에 사이트에서 변경 사항을 확인할 수도 있습니다.

Merge Request 파이프라인 사용 시작

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

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

  • rules: 각 작업에 규칙을 추가하여 작업이 실행되는 파이프라인을 구성합니다. Merge Request 파이프라인, 예약된 파이프라인 또는 다른 특정 상황에서 작업을 실행하도록 구성할 수 있습니다. 규칙은 위에서 아래로 평가되며, 규칙이 일치하면 작업이 파이프라인에 추가됩니다.
  • CI/CD 변수: 구성 파일과 스크립트 명령어에서 작업 동작을 구성하기 위해 이 환경 변수를 사용합니다. 사전 정의 CI/CD 변수는 매뉴얼으로 정의할 필요가 없는 변수입니다. 파이프라인에 자동으로 주입되어 파이프라인을 구성할 수 있게 해줍니다. 변수는 일반적으로 $VARIABLE_NAME 형식으로, 사전 정의 변수는 일반적으로 $CI_로 접두사가 붙습니다.

이 단계에서:

  • 새로운 기능 브랜치를 만들고 해당 브랜치에서 변경 사항을 만듭니다. 이때 기본 브랜치가 아닌 기능 브랜치에서 작업을 수행합니다.
  • 각 작업에 rules를 추가합니다:
    • 사이트는 기본 브랜치의 변경 사항에 대해서만 배포되어야 합니다.
    • 다른 작업은 Merge Request이나 기본 브랜치의 모든 변경 사항에 대해 실행되어야 합니다.
  • 이 파이프라인 구성을 사용하면 작업을 실행하지 않고 기능 브랜치에서 작업할 수 있으므로 리소스를 절약할 수 있습니다. 변경 사항을 확인할 준비가 되면 Merge Request을 만들고 Merge Request에서 실행될 작업이 구성된 파이프라인이 실행됩니다.
  • Merge Request이 승인되고 변경 사항이 기본 브랜치로 Merge되면 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'  # Merge Request의 소스 브랜치에 대한 모든 변경에 대해 실행
    - 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'  # Merge Request의 소스 브랜치에 대한 모든 변경에 대해 실행
    - 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'  # Merge Request의 소스 브랜치에 대한 모든 변경에 대해 실행
    - 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      # 기본 브랜치의 모든 변경에 대해 실행

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

앞으로의 파이프라인 구성 변경에 대해서도 모든 변경 사항에 대해 Merge Request과 기능 브랜치를 사용하도록 하세요. 다른 프로젝트 변경(예: Git 태그 생성 또는 파이프라인 스케줄 추가)은 규칙을 추가하지 않는 이상 파이프라인을 트리거하지 않습니다.

중복 구성 감소

현재 파이프라인에는 모두 동일한 rulesimage 구성을 가진 세 개의 작업이 포함되어 있습니다. 이러한 규칙을 반복하는 대신에 extendsdefault를 사용하여 단일 진실의 근원을 만드세요.

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

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

이 단계에서는:

  • build-job, lint-markdown, test-html에서 반복되는 규칙을 보유하기 위해 .standard-rules 숨겨진 작업을 추가하세요.
  • extends를 사용하여 세 개의 작업에서 .standard-rules 구성을 재사용하세요.
  • image 기본값을 node로 정의하기 위해 default 섹션을 추가하세요.
  • pages 배포 작업에는 기본 node 이미지가 필요하지 않으므로 극히 작고 빠른 이미지인 busybox를 명시적으로 사용하세요.
stages:
  - build
  - test
  - deploy

default:               # `image` 키워드의 기본값을 정의하는 default 섹션을 추가하세요
  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

본 파이프라인 구성을 기본 브랜치에 커밋하려면 Merge Request을 사용하세요. 파일은 더 간단해졌지만 이전 단계와 동일한 동작을 해야 합니다.

여러분은 방금 전체 파이프라인을 만들고 더 효율적으로 최적화했습니다. 훌륭한 작업입니다! 이제 이 지식을 활용하여 CI/CD YAML 구문 참조에서 나머지 .gitlab-ci.yml 키워드에 대해 학습하고 나만의 파이프라인을 구축할 수 있습니다.