GitLab CI/CD · 설정 언어로서의 .gitlab-ci.yml · 이론
잡 하나가 담고 있는 것
한 줄 요약
잡은 최상위 키 하나이고, 그 안에서 실행을 만드는 것은 script 하나뿐이며, 나머지 키들은 전부 "언제·어디서·무엇을 들고" 그 script 를 돌릴지를 정하는 장식이다.
왜 이게 필요했나
파이프라인 설정을 처음 읽는 사람이 가장 많이 하는 착각은 키 이름을 외우면 된다고 생각하는 것이다. 그런데 실제로 막히는 지점은 문법이 아니라 구조다. stage 를 적었는데 잡이 안 보이고, image 를 적었는데 다른 이미지가 쓰이고, 똑같은 다섯 줄을 잡 여섯 개에 복사해 두었다가 한 곳만 고쳐 사고가 난다. 세 경우 모두 원인은 하나다 — 무엇이 잡이고 무엇이 잡이 아닌지, 그리고 값이 어디서 흘러 들어오는지를 모르는 것.
어떻게 동작하나
최상위 매핑의 키 하나가 잡 하나다. 다만 세 가지는 예외다. 첫째, stages·variables·default·include·workflow 는 예약된 전역 설정이라 잡이 아니다. 둘째, 이름이 점으로 시작하는 키(.python-base 같은 것)는 숨김 잡이라서 파이프라인에 실행 대상으로 올라가지 않는다. 셋째, 값이 매핑이 아니면 잡이 될 수 없다.
잡을 잡으로 만드는 것은 script 다. script 가 없는 잡은 설정 오류이고, GitLab 은 그런 파이프라인을 아예 만들지 않는다. 이건 사소한 규칙이 아니라 설계 의도다 — 실행할 것이 없는 잡은 존재할 이유가 없다.
나머지 키는 세 갈래로 묶어 두면 외울 것이 줄어든다. 어디서 도는가는 image·services·tags 가 정한다. 언제 도는가는 stage·needs·rules 가 정한다. 무엇을 들고 도는가는 variables·artifacts·cache·before_script 가 정한다. 실습에서 만질 키는 전부 이 세 갈래 안에 있다.
중복을 줄이는 장치는 두 개인데 성격이 다르다. default 는 아무것도 안 정한 잡에게 적용되는 바닥값이다. 전역이고, 잡이 같은 키를 직접 쓰면 그쪽이 이긴다. extends 는 지정한 조각을 깊게 병합해서 가져온다. 그래서 조각에 before_script 를 두고 잡에서 script 만 다르게 쓰는 식의 재사용이 된다. 비슷해 보이는 YAML 앵커(&/*)는 병합이 아니라 그 자리에 통째로 펼치는 것이고, 한 문서 안에서만 유효해서 include 로 가져온 파일 사이에서는 쓸 수 없다. 그래서 실무 템플릿은 앵커가 아니라 extends 로 쓴다.
실무에서 자주 나는 사고
가장 흔한 사고는 들여쓰기다. script 를 한 단계 깊게 넣으면 그것이 잡의 키가 아니라 앞 키의 하위 항목이 되고, 잡은 script 없는 잡이 되어 설정 검증에서 거부되거나 목록에서 조용히 사라진다. YAML 은 아무 불평도 하지 않는다는 점이 이 사고를 오래 끌게 만든다.
두 번째로 흔한 것은 조각을 만들면서 점을 빼먹는 것이다. python-base 라고 쓰면 그것은 물려주는 조각이 아니라 매 파이프라인마다 실제로 도는 잡이 된다. 대개 script 가 없으니 설정 오류로 잡히지만, 조각에 script 를 넣어 둔 경우에는 정상적으로 돌면서 아무 의미 없는 잡 하나가 계속 실행된다.
다음 퀴즈에서 볼 것
잡과 잡이 아닌 것의 경계, script 의 위상, default 와 extends 와 앵커의 차이를 구분해 본다. 어느 것이 바닥값이고 어느 것이 병합인지가 갈리는 지점을 눈여겨보라.