본문 바로가기

개발(합니다)/OS&Dev&Infra&AWS

[Gitlab-CI/CD] .gitlab-ci.yml 사용 방법

반응형

gitlab-ci에 대한 전체적인 그림

Gitlab-CI/CD를 잘 다루려면 .gitlab-ci.yml의 동작 방식에 대해서 정리합니다.

관련 예제는 아래 사이트에서 확인할 수 있습니다.
gitlab-ci/cd

.gitlab-ci.yml

Gitlab-CI/CD의 파이프라인은 .gitlab-ci.yml 파일로 구성되며
파일에 작성 된 스크립트에 따라 순차적으로 동작합니다.

  • 파이프라인의 구조 및 순서를 정의
  • Gitlab Runner를 이용해서 실행할 일들
  • 특정 상황에 따라 실행할 일들

Gitlab-CI/CD의 실행 단위가 JOB으로 구성되어 있어서 위에 설명에도 일들이라고 명시했습니다.

JOB

관련 키워드는 아래 사이트에서 확인 할 수 있습니다.
.gitlab-ci.yml

  • 최상위 요소로 script가 반드시 있어야 함
  • 실행 해야 하는 상황과 조건을 정의
test: 
    script: "node install"
build:
    script: "node run"

JOB 동작

키워드별 동작에 대한 설명입니다.

스크립트 작성 시 참고하려고 작성했습니다.

키워드 설명
after_script 작업 후 실행되는 명령 집합을 재정의합니다.
allow_failure 작업 실패를 허용합니다. 실패한 작업으로 인해 파이프 라인이 실패하지 않습니다.
artifacts 성공시 작업에 첨부 할 파일 및 디렉토리 목록입니다.
artifacts:paths, artifacts:exclude, artifacts:expose_as, artifacts:name, artifacts:untracked, artifacts:when, artifacts:expire_in, artifacts:reports
before_script 작업 전에 실행되는 명령 집합을 재정의합니다.
cache 후속 실행 사이에 캐시되어야하는 파일 목록입니다.
cache:paths, cache:key, cache:untracked, cache:policy
coverage 주어진 작업에 대한 코드 검사 설정.
dependencies 아티팩트를 가져올 작업 목록을 제공하여 특정 작업에 전달되는 아티팩트를 제한하십시오.
environment 작업이 배포되는 환경의 이름입니다.
environment:name, environment:url, environment:on_stop, environment:auto_stop_in, environment:action
except 작업이 생성되지 않는시기를 제어합니다.
extends 이 작업이 상속하는 구성 항목입니다.
image Docker 이미지를 사용하십시오.
image:name, image:entrypoint
include 외부 YAML 파일을 포함합니다.
include:local, include:file, include:template, include:remote
inherit 모든 작업이 상속하는 전역 기본값을 선택합니다.
interruptible 새로운 실행으로 중복 될 때 작업을 취소 할 수 있는지 여부를 정의합니다.
needs 단계 순서보다 일찍 작업을 실행하십시오.
only 작업 생성시기를 제어합니다.
pages GitLab 페이지에서 사용할 작업 결과를 업로드합니다.
parallel 병렬로 실행해야하는 작업 인스턴스 수입니다.
release 러너에게 릴리스 객체 를 생성하도록 지시 합니다.
resource_group 작업 동시성을 제한합니다.
retry 실패시 작업을 자동 재 시도 할 수있는시기 및 횟수입니다.
rules 작업의 선택한 속성 및 생성 여부를 평가하고 결정하기위한 조건 목록입니다.
only/except 와 함께 사용 불가
script 러너가 실행하는 쉘 스크립트입니다.
secrets CI / CD는 작업에 필요한 비밀입니다.
services Docker 서비스 이미지를 사용하십시오.
services:name, services:alias, services:entrypoint, services:command
stage 작업 단계를 정의합니다.
tags 러너를 선택하는 데 사용되는 태그 목록입니다.
timeout 프로젝트 전체 설정보다 우선하는 사용자 지정 작업 수준 제한 시간을 정의합니다.
trigger 다운 스트림 파이프 라인 트리거를 정의합니다.
variables 작업 수준에서 작업 변수를 정의합니다.
when 작업 실행시기.
when:manual, when:delayed

작업에서 사용할 수 없는 키워드입니다.

  • image
  • services
  • stages
  • types
  • before_script
  • after_script
  • variables
  • cache
  • include

전역 파라미터

키워드 설명
stages 파이프라인 단계의 이름과 순서
workflow 실행되는 파이프라인의 유형을 제어
include 다른 yml 팦일에서 구성을 가져옴

전역 파라미터는 위 표처럼 3가지고 구분하며

전역 파라미터는 모든 JOB에서 공통으로 사용할 경우 쓰이며 default 키워드로 설정합니다.

default 키워드가 사용 가능한 파라미터는 아래와 같습니다.

  • after_script
  • artifacts
  • before_script
  • cache
  • image
  • interruptible
  • retry
  • services
  • tags
  • timeout
default:
  image: ruby:3.0

rspec:
  script: bundle exec rspec

rspec 2.7:
  image: ruby:2.7
  script: bundle exec rspec

stages

JOB이 실행되는 단계를 의미하며 동일한 stage 안에 있는 JOB들은 병렬적으로 실행됩니다.

- test
- build
- deploy

include

외부에 작성한 yml 파일을 포함할 수 있고 CI/CD 구성을 각각 다른 파일로 구분하여 작성할 수 있습니다.
전역 기본 변수나 중복되는 구성에 대한 부분을 별도로 작성할 수 있습니다.

  • local : 로컬 프로젝트 repository 파일들
  • file : 다른 프로젝트 repository 파일들
  • remote : 원격 URL의 파일들과 공개되어 access 가능함
  • template : Gitlab에서 제공하는 템플릿

script

스크립트에서 특수 문자가 나오는 경우에는 따옴표로 묶어주어야 합니다.

{, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, @, `.

아래처럼 작성하여 사용할 수 있습니다.

job:
  script:
    - uname -a
    - bundle exec rspec

스크립트 명령이 0이 아닌 exit code를 반환하는 경우에는 job이 실패하게 되므로 변수에 exit code를 저장하여 처리합니다.

job:
  script:
    - false || exit_code=$?
    - if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi;

stage

Runner는 한번에 하나의 JOB을 처리하지만 병렬적으로 처리하도록 구성할 수 있습니다.

병렬로 처리하는 벙법

  • Runner의 concurrent 셋팅
  • 다른 Runner를 만들어서 따로 실행

.gitlab-ci.yml 작성 순서와 관계 없이
.pre 는 항상 파이프라인 첫 번째로 실행되고
.post 는 항상 파이프라인 마지막에 실행됩니다.

stages:
  - .pre
  - a
  - b
  - .post

stages:
  - a
  - .pre
  - b
  - .post

stages:
  - a
  - b

extends

템플릿 JOB을 설정하고 extends 키워드로 상속을 할 수 있습니다.

.tests:
  script: rake test
  stage: test
  only:
    refs:
      - branches

rspec:
  extends: .tests
  script: rake rspec
  only:
    variables:
      - $RSPEC

=========================
위 실행 시 아래와 같이 변경
=========================
rspec:
  script: rake rspec
  stage: test
  only:
    refs:
      - branches
    variables:
      - $RSPEC

주의 할 점은 최대 3 depth 이상의 상속은 피하는게 좋으며
includeextends를 함께 사용하면 좋은 구성으로 관리할 수 있습니다.

rules

파이프라인을 최대한 활용하려면 only/except 대신 rules를 사용하길 권장합니다.

rules는 파이프라인에서 JOB을 포함하거나 제외할 경우에 사용합니다.
단, only/except와 함께 사용하면 key may not be used with rules 오류가 발생합니다.

rules에서 허용하는 JOB 속성은 whenallow_failure 입니다.

  • when : when:on_success가 기본 값이고 when:delayed 사용시엔 start_in도 정의해야 함
  • allow_failure : allow_failure_ false가 기본값
job:
  script: echo "Hello, Rules!"
  rules:
    - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH'
      when: never
    - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/'
      when: manual
      allow_failure: true
    - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME'


docker build:
  script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
      changes:
        - Dockerfile
      when: manual
      allow_failure: true

needs

다른 작업을 기다리지 않고 동시에 여러개의 job을 실행할 수 있습니다.

아래 예제는 4개의 실행 경로를 생성합니다.

  • Linter : 스테이지가 완료 lint 될때까지 기다리지 않고 작업이 즉시 실행됩니다.
  • Linux 경로 : linux:rspeclinux:rubocop 작업은 linux:build가 완료 될 때까지 기다리지 않고 작업이 완료 되는 즉시 실행합니다.
  • macOS 경로 : mac:rspecmac:rubocop 작업은 mac:build 완료 될 때까지 기다리지 않고 작업이 완료 되는 즉시 실행합니다.
  • production 곧 모든 이전 작업 실행 완료인 경우
linux:build:
  stage: build
  script: echo "Building linux..."

mac:build:
  stage: build
  script: echo "Building mac..."

lint:
  stage: test
  needs: []
  script: echo "Linting..."

linux:rspec:
  stage: test
  needs: ["linux:build"]
  script: echo "Running rspec on linux..."

linux:rubocop:
  stage: test
  needs: ["linux:build"]
  script: echo "Running rubocop on linux..."

mac:rspec:
  stage: test
  needs: ["mac:build"]
  script: echo "Running rspec on mac..."

mac:rubocop:
  stage: test
  needs: ["mac:build"]
  script: echo "Running rubocop on mac..."

production:
  stage: deploy
  script: echo "Running production..."

allow_failure

JOB이 실패할 경우 다른 작업들에 영향을 주지 않도록 하기 위해 사용합니다.
rules를 사용하지 않는 경우에는 when:manual을 사용하는 수동 작업을 제외하고 기본 값은 false입니다.

job1:
  stage: test
  script:
    - execute_script_that_will_fail
  allow_failure: true

job2:
  stage: test
  script:
    - execute_script_that_will_succeed

job3:
  stage: deploy
  script:
    - deploy_to_staging

when

on_success : 이미 실행된 stage 의 모든 JOB 이 성공한 경우에만 JOB 을 실행
on_failure : 이미 실행된 stage 의 JOB 이 하나 이상 실패한 경우에만 JOB 을 실행
always : 이미 실행된 stage 의 JOB 상태에 상관없이 JOB 을 실행
manual : JOB 을 수동으로 실행
delayed : 특정 시간이 지나고 JOB 을 실행
never : rules 와 함께 사용하면 JOB 을 실행 안함, workflow:rules 와 함께 사용하면 파이프라인을 실행 안함

stages:
  - build
  - cleanup_build
  - test
  - deploy
  - cleanup

build_job:
  stage: build
  script:
    - make build

cleanup_build_job:
  stage: cleanup_build
  script:
    - cleanup build when failed
  when: on_failure

test_job:
  stage: test
  script:
    - make test

deploy_job:
  stage: deploy
  script:
    - make deploy
  when: manual

cleanup_job:
  stage: cleanup
  script:
    - cleanup after jobs
  when: always

environment

특정 환경에 배포되도록 정의할 경우 environment를 사용합니다.
지정했지만 해당 이름의 environment가 없으면 새로운 environment를 자동으로 생성힙니다.

deploy to production:
  stage: deploy
  script: git push production HEAD:main
  environment: production

보통 qa, stagins, production으로 이름을 사용합니다.

artifacts

artifacts는 JOB이 완료 된 후 첨부되는 파일이나 디렉토리 목록 지정하는 경우에 사용됩니다.
JOB이 완료 되면 artifacts가 Gitlab으로 전송되고 크기가 1G가 넘지 않으면 Gitlab UI에서 다운로드 할 수 있습니다.

trigger

자식 파이프라인 생성 방법은은 하위 파이프라인 CI 구성이 포함된 yml파일의 경로를 지정하면 됩니다.
단일 저장소이고 특정 파일이 변경될 경우에만 동작하길 원하면 only:change를 사용하면 됩니다.

trigger:strategy
트리거에 대한 전략으로 trigger JOB은 다운스트림 파이프라인이 생성되면 바로 성공 상태로 완료되고,
다운스트림 파이프라인이 완성될 때까지 기다리게 하려면 strategy:depend를 사용하면 됩니다.

create-artifact:
  stage: build
  script: echo 'sample artifact' > artifact.txt
  artifacts:
    paths: [artifact.txt]

child-pipeline:
  stage: test
  trigger:
    include: child.yml
    strategy: depend
  variables:
    PARENT_PIPELINE_ID: $CI_PIPELINE_ID

pages

pages는 정적 : static 컨텐츠 업로드할 경우에 사용합니다.

  • 모든 static 파일은 public/ 디렉토리에 위치
  • public/ 디렉토리에 대한 경로가 있는 artifacts 정의
pages:
  stage: deploy
  script:
    - mkdir .public
    - cp -r * .public
    - mv .public public
  artifacts:
    paths:
      - public
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

tags

tags는 모든 러너 목록에서 특정 러너를 선택할 경우 사용합니다.

windows job:
  stage:
    - build
  tags:
    - windows
  script:
    - echo Hello, %USERNAME%!

osx job:
  stage:
    - build
  tags:
    - osx
  script:
    - echo "Hello, $USER!"
반응형