LabHub
배우기 러닝패스 코스

GitLab CI/CD

Tagging nightly shipped a release

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

브랜치·태그·파일 존재·원격과의 변경에 따라 잡이 목록에 들어가고 빠지는 것을 상황을 바꿔 가며 확인하고, 규칙의 순서와 규칙이 정하는 변수로 배포 정책을 설정에 새깁니다.

왜 중요한가

rules 는 잡이 시작할 때 묻는 조건이 아니라 파이프라인이 만들어질 때 목록을 정하는 규칙입니다. 첫 매치만 적용되므로 항목의 순서가 곧 정책이고, 순서를 잘못 두면 오류 없이 배포가 사라지거나 엉뚱한 태그에 릴리스가 나갑니다. changes 는 무엇과 비교하느냐에 따라 결과가 바뀌고, 조건과 값(배포 대상)을 떨어뜨려 두면 둘이 어긋나는 날이 옵니다. 이런 차이는 설정을 읽는 것만으로는 잘 보이지 않아서 상황을 바꿔 실행해 봐야 합니다.

단계

  1. /root/glci-rules 을 git 저장소로 만들고 .gitignore.gitlab-ci-local/ 를 두세요. .gitlab-ci.yml 에 stages [build, deploy], 조건 없는 잡 unit(build, echo "unit log=$LOG_LEVEL"), 그리고 $CI_COMMIT_BRANCH == "main" 일 때만 만들어지는 deploy-staging(deploy, echo staging)을 두고 main 브랜치에 커밋하세요. 채점기는 사본에서 feature/login 브랜치로 옮겨 deploy-staging 이 목록에서 사라지는지 봅니다.
  2. release-notes(deploy, echo notes)를 $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/ 일 때만 만들어지게 더하고 커밋하세요. gitlab-ci-local 은 git 태그를 읽지 않으므로 --variable CI_COMMIT_TAG=v1.2.0 으로 태그 파이프라인을 흉내 냅니다. v1.2.0 이면 목록에 있고, nightly 나 태그 없음이면 없어야 합니다.
  3. publish(deploy, echo publish)의 rules 를 세 항목으로 두세요: 태그가 있으면 when: on_success, main 브랜치면 when: manualallow_failure: false, 그 밖에는 when: never. 커밋합니다. 목록에서 main 이면 manual(allowFailure false), 태그 변수가 있으면 on_success, feature 브랜치면 없어야 합니다.
  4. docker-build(build, echo docker)를 rules: - exists: [Dockerfile] 로 더하고 커밋하세요. 이 저장소에는 아직 Dockerfile 을 만들지 않습니다. 채점기는 사본에 Dockerfile 을 넣었을 때만 잡이 생기는지 봅니다.
  5. /root/glci-rules-origin.git 에 bare 저장소를 만들어 origin 으로 등록하고 main 을 push 한 뒤 git remote set-head origin main 을 실행하세요. 그다음 잡 docs-build(build, echo docs)를 rules: - changes: ["docs/**/*"] 로 더해 커밋하고 다시 push 합니다. 채점기는 사본에서 docs 아래를 고친 브랜치와 다른 파일만 고친 브랜치를 만들어, 앞의 경우에만 docs-build 가 생기는지 봅니다.
  6. deploy(deploy, echo "target=$DEPLOY_TARGET")를 더하세요. rules 는 태그면 variables: {DEPLOY_TARGET: production}, main 이면 variables: {DEPLOY_TARGET: staging} 입니다. 커밋하고 push 합니다. main 에서 실행하면 target=staging, 태그 변수를 주면 target=production 이 찍혀야 합니다.
  7. .gitlab-ci.yml 맨 위에 workflow: rules: 를 두세요. main 이면 variables: {LOG_LEVEL: warn}, 그 밖에는(when: always) variables: {LOG_LEVEL: debug} 입니다. 커밋하고 push 합니다. main 에서 unit 로그는 unit log=warn, feature 브랜치에서는 unit log=debug 여야 합니다.

참고

main 에서만 스테이징 배포를 만든다

/root/glci-rules 을 git 저장소로 만들고 .gitignore.gitlab-ci-local/ 를 두세요. .gitlab-ci.yml 에 stages [build, deploy], 조건 없는 잡 unit(build, echo "unit log=$LOG_LEVEL"), 그리고 $CI_COMMIT_BRANCH == "main" 일 때만 만들어지는 deploy-staging(deploy, echo staging)을 두고 main 브랜치에 커밋하세요. 채점기는 사본에서 feature/login 브랜치로 옮겨 deploy-staging 이 목록에서 사라지는지 봅니다.

rules 는 파이프라인을 만들 때 평가됩니다. 조건이 하나도 맞지 않으면 그 잡은 'never' 로 목록에서 빠집니다. 브랜치를 바꿔 gitlab-ci-local --list-csv-all 로 when 칸을 비교해 보세요.

태그 이름의 모양까지 보고 릴리스 노트를 만든다

release-notes(deploy, echo notes)를 $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/ 일 때만 만들어지게 더하고 커밋하세요. gitlab-ci-local 은 git 태그를 읽지 않으므로 --variable CI_COMMIT_TAG=v1.2.0 으로 태그 파이프라인을 흉내 냅니다. v1.2.0 이면 목록에 있고, nightly 나 태그 없음이면 없어야 합니다.

=~ 는 정규식 비교입니다. 태그 변수는 태그 파이프라인에서만 채워지므로 그 존재만 보면 nightly 같은 임시 태그에도 릴리스가 나갑니다. 정규식은 슬래시로 감쌉니다.

첫 매치만 적용된다 — 순서가 곧 정책이다

publish(deploy, echo publish)의 rules 를 세 항목으로 두세요: 태그가 있으면 when: on_success, main 브랜치면 when: manualallow_failure: false, 그 밖에는 when: never. 커밋합니다. 목록에서 main 이면 manual(allowFailure false), 태그 변수가 있으면 on_success, feature 브랜치면 없어야 합니다.

위에서부터 읽다가 처음 맞는 항목 하나만 씁니다. 조건 없는 when: never 를 가운데에 두면 그 아래 항목은 영영 읽히지 않고, 아무 오류도 나지 않습니다. manual 잡을 진짜 승인 게이트로 쓰려면 allow_failure: false 를 함께 둡니다.

Dockerfile 이 있는 저장소에서만 이미지를 굽는다

docker-build(build, echo docker)를 rules: - exists: [Dockerfile] 로 더하고 커밋하세요. 이 저장소에는 아직 Dockerfile 을 만들지 않습니다. 채점기는 사본에 Dockerfile 을 넣었을 때만 잡이 생기는지 봅니다.

exists 는 저장소에 그 경로의 파일이 있는지를 봅니다. 여러 저장소가 같은 템플릿을 include 할 때, 저장소마다 설정을 고치지 않고 해당하는 잡만 켜는 데 씁니다.

문서가 바뀐 브랜치에서만 문서를 빌드한다

/root/glci-rules-origin.git 에 bare 저장소를 만들어 origin 으로 등록하고 main 을 push 한 뒤 git remote set-head origin main 을 실행하세요. 그다음 잡 docs-build(build, echo docs)를 rules: - changes: ["docs/**/*"] 로 더해 커밋하고 다시 push 합니다. 채점기는 사본에서 docs 아래를 고친 브랜치와 다른 파일만 고친 브랜치를 만들어, 앞의 경우에만 docs-build 가 생기는지 봅니다.

changes 는 '무엇과 비교한 변경인가' 가 핵심입니다. gitlab-ci-local 은 원격 기본 브랜치(origin/main)와 비교하므로 원격이 있어야 합니다. GitLab 의 브랜치 파이프라인은 직전 push 와, 병합 요청 파이프라인은 대상 브랜치와 비교합니다.

어느 규칙에 걸렸는지가 배포 대상을 정한다

deploy(deploy, echo "target=$DEPLOY_TARGET")를 더하세요. rules 는 태그면 variables: {DEPLOY_TARGET: production}, main 이면 variables: {DEPLOY_TARGET: staging} 입니다. 커밋하고 push 합니다. main 에서 실행하면 target=staging, 태그 변수를 주면 target=production 이 찍혀야 합니다.

rules 항목의 variables 는 그 항목에 걸렸을 때만 잡에 들어갑니다. 조건과 값을 한곳에 두면 '태그인데 staging 으로 나갔다' 같은 불일치가 구조적으로 사라집니다.

파이프라인 전체의 값은 workflow 에서 정한다

.gitlab-ci.yml 맨 위에 workflow: rules: 를 두세요. main 이면 variables: {LOG_LEVEL: warn}, 그 밖에는(when: always) variables: {LOG_LEVEL: debug} 입니다. 커밋하고 push 합니다. main 에서 unit 로그는 unit log=warn, feature 브랜치에서는 unit log=debug 여야 합니다.

workflow:rules 는 파이프라인을 만들지 말지와 파이프라인 전체에 들어갈 변수를 정합니다. 잡마다 같은 조건을 반복하지 않아도 됩니다. 병합 요청과 브랜치 파이프라인이 겹치는 것을 막는 곳도 여기지만, 그 동작은 GitLab 서버에서만 확인할 수 있습니다.