깃랩 CI 파이프라인 워크플로우는 기본적으로 rules로 각 작업(job)의 실행 여부를 평가 후에 워크플로우를 생성합니다.
그렇기 때문에 파이프라인을 동적으로 생성, 실행시키긴 위해선 기본적으로 rules if 키워드 등으로 작업 생성을 제어합니다.
기본적으로 rules if 키워드는 gitlab에서 제공되는 predefined variables(https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)와 함께 사용됩니다.
그리고 그 값에 따라 해당 job이 생성되는지가 파이프라인 생성 단계에서 평가됩니다.
만약 job생성 여부를 predefined variables가 아닌 다른 variable로 평가하고 싶거나 job에서 실행되는 script로 제어하고 싶을 땐 어떻게 해야할까요?
이 부분에 대해서 제가 시도했던 방법들은 다음과 같습니다.
시도 1. variable(트리거 여부 variable 넘겨주어 동적 variable)로 제어
gitlab ci에서 작업간의 variable을 전달해 주기 위해서는 artifacts:reports:dotenv 키워드를 이용하여 variable을 넘겨 줄 수 있습니다.
다음과 같이 사용할 수 있습니다.
sample_job:
...
script:
- echo "NEW_VAR=value" >> sample.env
artifacts:
artifacts:
reports:
dotenv:
sample.env
next_job:
...
script:
# print value
- echo $NEW_VAR
다만 저의 경우에는 rules if는 artifact로 넘겨준 varialbe은 조건 평가 시점에서 사용할 수 없기에 다른 job에서 넘겨받은 변수로는 작업의 파이프라인 포함 여부에는 영향을 줄 수 없어 이 방법을 사용하지 못했습니다.
시도2. 전역 변수를 활용
이 경우에는 job에서 공통적으로 사용할 수 있는 전역변수를 활용하여 작업 생성을 제어하려고 했었습니다.
variables:
SAMPLE_VAR="sample value"
sample-job:
...
script:
- $SAMPLE_VAR="new value"
next-job:
...
script:
# print "sample value"
- echo $SAMPLE_VAR
하지만 전역변수로 생성한 변수는 특정 job에서 해당 변수의 값을 변경하여도 그 job내에서만 변경된 값이 유효하기에 다음 작업에서 사용할 수 없어 저에게 적합한 방법은 아니었습니다.
해결 방법1. 스크립트 분기에서 바로 다음 job을 트리거한다.
가장 직관적인 방법입니다. script의 분기에서 다음 작업을 수행해야하는 경우, 파이프라인을 트리거하고, 아닌 경우에는 job을 종료하면 됩니다.
그렇다면 파이프라인 트리거는 어떻게 할까요?
3가지 방법으로 나뉩니다.
1. webhook
2. trigger 키워드
3. script에서 API 요청
우선 webhook은 push와 같은 다양한 gitlab event에 파이프라인을 트리거하는 방법인데요.
여기에서는 일반적인 ci 워크플로우에서의 파이프라인을 트리거하는 방법을 알아보는 것이기 때문에 제외하겠습니다.
trigger 키워드 역시 작업 내에서 trigger 키워드를 이용하여 트리거할 ci에 대해 명시하는 방법으로 진행합니다. 하지만 이 방법 역시, script에서 바로 다음 파이프라인(job)을 트리거할 수 없습니다.
# parent-child pipeline trigger 예시
trigger_job:
trigger:
include:
- local: path/to/child-pipeline.yml
내용이 궁금하신 분은 아래를 참고하여 주세요,
Downstream pipelines | GitLab
GitLab product documentation.
docs.gitlab.com
script에서 파이프라인 트리거 API 요청하기
curl --request POST \
--form token=<token> \
--form ref=<ref_name> \
"https://gitlab.example.com/api/v4/projects/<project_id>/trigger/pipeline"
token: gitlab pipelie trigger token
ref: 프로젝트의 브랜치나 태그
project_id: 고유한 프로젝트 ID
해당 API 호출 명령어를 보면, 파이프라인 트리거 권한을 받기위한 token이 필요합니다.
token은 pipeline trigger token이라는 프로젝트에서 발급받을 수 있는 별도의 토큰을 발급받고, 요청에 같이 포함해야 합니다.
pipeline token을 발급받고 해당 토큰을 보호하기 위해 CI/CD variable로 해당 토큰 값을 저장하고, 실제 .gitlab-ci.yml에선 CI/CD variable을 사용하는 식으로 사용 할 것입니다.
제가 진행하였던 작업 특성상, gitlab ci를 잘 모르는 사람들도 사용할 수 있는 template을 개발하는 것이 목적이었고, 템플릿 사용자들이 프로젝트에 템플릿을 사용할 때마다 토큰을 발급받고, CI/CD varialbe을 생성하는 것이 꽤 복잡한 과정이라 판단하여 이 방법은 제외하였습니다.
해결 방법 2. 파이프라인 트리거 여부를 제어하는 작업(job) 생성
(1)파이프라인 트리거여부 변수 생성하는 작업 -> (2)변수를 받아 해당 변수에 따라 작업의 성공여부를 결정하는 작업 생성 -> (3) 2의 작업에 의존하는 다음 작업은 2의 작업이 성공하면 작업 실행, 2의 작업이 실패하면 파이프라인이 실패하여 작업이 실행되지 않게 됨.
기존 목표 파이프라인이 (1)작업에서 다음 작업을 실행할 지 여부를 판단 -> (2) 다음 작업 실행이었다면,
(1)과 (2) 사이에 작업 하나를 추가하여, 새로 추가한 작업이 성공하면 자연스럽게 다음 작업이 실행되는 것이고, 실패하게 된다면 파이프라인이 실패하여 다음 작업을 실행하지 않는 구조입니다.
시나리오에서 작업 1,2,3 이 있다고 가정하겠습니다.
- 작업1에서 다음 작업을 실행하지 않기 위한 변수를 생성합니다. (해당 변수의 값 예시 : false)
- artifacts:reports:dotenv로 작업2로 해당 변수를 넘겨줍니다.
- 작업2의 script에서 해당 변수를 확인 후, 값이 false이면 script에서 작업을 비정상 종료를 합니다. (exit 1)
- 작업3은 앞의 작업2가 실패하였으므로, allow_failure의 값이 false(기본값)인 경우에 자연스럽게 작업3은 실행되지 않고, 파이프라인은 종료됩니다.
다소 깔끔하진 않은 방법입니다.
다음 작업을 실행하지 않는 경우라면 사용자가 의도한대로 동작을 하는 것이지만, 작업 성공 여부가 실패로 표기되기 때문에 사용자 입장에서는 직관적이지 않은 방법입니다.
해결 방법 3. Dynamic child pipelines로 제어
제가 최종적으로 적용한 방법입니다.
gitlab ci에선 이러한 상황을 위해 변경되는 콘텐츠에 대해 동적으로 파이프라인을 생성할 수 있는 방법을 제공하고 있습니다.
기존에는 변수로 파이프라인을 제어하려고 하였다면, 이번에는 ci파일 자체를 동적으로 생성하는 것입니다.
원리는 다음과 같습니다.
- job(작업)에서 각각의 분기에 따라 gitlab ci파일을 생성합니다.
- 그리고 해당 작업에서 생성한 ci파일을 다음 작업의 아티팩트(artifact)로 내보냅니다.
- 다음 작업은 이전 작업에서 생성된 아티팩트를 트리거하는 작업으로 생성합니다.
- 아티팩트에 명시된 작업이 수행됩니다.
이로써 사용자는 분기에 따라 사용자가 원하는 동작을 수행하는 작업을 아티팩트(ci)파일로 할 수 있게 됩니다.
저는 다음과 같이 작성하였습니다. 참고하시길 바랍니다.
generate-config:
stage: build
script:
-|
if ~ 조건이면
파이프라인 트리거하는 gitlab-ci.yml파일 생성
fi
else
작업을 종료하는 gitlab-ci.yml파일 생성
fi
artifacts:
paths:
- 생성된 gitlab-ci.yml파일
child-pipeline:
stage: test
trigger:
include:
- artifact: 생성된 gitlab-ci.yml파일
job: 아티팩트로 받은 ci파일 내부의 작업
이를 통해 자연스럽게 script내에서 분기로 동적으로 작업을 생성할 수 있게 되었고, 사용자 역시 적절한 권한을 가진 파이프라인 주체자가 있다면 아무런 설정을 하지 않아도 해당 ci를 적용할 수 있다는 장점을 가지게 됩니다.
공식 문서를 보고 싶으시다면 아래의 링크를 참고하세요.
Downstream pipelines | GitLab
GitLab product documentation.
docs.gitlab.com
요구사항에 맞춰 동적으로 파이프라인을 구성해야 하는 문제를 다행히도 gitlab에서 제공하는 기능을 통해 해결할 수 있었습니다.
본인 상황에 맞춰 위의 방법들을 적절히 사용하면 원하는 방향으로 파이프라인을 구성하실 수 있을 것 같습니다.
틀린 내용 지적이나 궁금하신 점들은 댓글을 남겨주시면 감사하겠습니다.
'CI & CD' 카테고리의 다른 글
ArgoCD Image Updater은 무엇이고 어떻게 사용할까요? (0) | 2024.10.11 |
---|---|
Argo rollouts 고급 배포 전략 적용 - 1편 (canary, blue green) 기본 개념 (1) | 2024.04.07 |
신입이 이해한 GitOps (0) | 2023.12.25 |
GitOps 몸으로 배우기 (feat. 작업물 날려먹기) (0) | 2023.12.13 |