CI/CD 파이프라인 · 테스트 게이트 · 실습
병합을 막는 게이트 만들기
목표
테스트 러너, 커버리지 게이트, 재시도, 격리를 셸로 만들고 이 신호들을 하나의 병합 판정으로 합친다.
왜 중요한가
게이트의 값어치는 통과시키는 능력이 아니라 막는 능력에서 나온다. 그래서 러너는 실패를 정확히 세야 하고, 커버리지 비교는 경계값에서 흔들리면 안 되고, 재시도는 상한이 있어야 한다. 무한 재시도는 실패를 감추는 것이고, 격리는 불안정한 테스트가 팀 전체를 막지 않게 하되 그 사실을 리포트에 남기는 타협이다. 마지막 리포트가 중요한 이유는, 사람이 아니라 브랜치 보호의 required status checks 같은 자동 장치가 이 판정을 읽고 병합을 막기 때문이다. 수치와 판정이 어긋난 리포트는 게이트를 무의미하게 만든다.
단계
1. /root/ci2/run-tests.sh <디렉터리> 를 만들고 실행 권한을 준다. 인자로 받은 디렉터리의 *.sh 파일을 하나씩 실행하고, 마지막에 passed=<수> failed=<수> skipped=<수> 요약을 한 줄로 출력한다. 모두 통과하면 종료코드 0. 테스트 파일에는 실행 권한이 없을 수 있으므로 bash "$f" 형태로 실행한다.
2. 실패하는 테스트가 섞여 있어도 나머지를 끝까지 실행한 뒤, 마지막에 0 이 아닌 코드로 끝낸다. 통과 2개와 실패 1개가 있으면 요약은 passed=2 failed=1 이 되어야 한다.
3. 빈 디렉터리를 받으면 passed=0 failed=0 과 종료코드 0 을 낸다. 이때 대상 디렉터리 안에 로그 등 파일을 만들지 않는다.
4. /root/ci2/gate-coverage.sh <커버리지파일> <임계값> 을 만든다. 커버리지 파일은 covered=80 total=100 형식의 한 줄이다. 퍼센트는 covered * 100 / total 이고, 임계값 이상이면 종료코드 0, 미만이면 0 이 아닌 코드를 낸다(같으면 통과). 실패할 때는 실제 퍼센트 값을 출력한다.
5. /root/ci2/retry.sh <최대시도횟수> <명령...> 을 만든다. 명령이 성공하면 즉시 멈추고 0 을 내고, 최대 횟수까지 모두 실패하면 0 이 아닌 코드를 낸다. 실제 시도 횟수는 최대 횟수를 절대 넘지 않는다.
6. 대상 디렉터리에 quarantine.txt 가 있으면 거기 적힌 파일명(한 줄에 하나)은 실행하지 않고 skipped 로 센다. 격리된 테스트는 failed 로 세지 않으며, 나머지가 모두 통과하면 종료코드는 0 이다.
7. /root/ci2/gate.sh <테스트디렉터리> <커버리지파일> <임계값> 을 만든다. 테스트와 커버리지 두 조건이 모두 통과일 때만 종료코드 0 을 내고, 하나라도 실패면 0 이 아닌 코드를 낸다.
8. /root/ci2/gate-report.json 을 만든다. 필드는 tests.passed, tests.failed, tests.skipped, coverage.pct, coverage.threshold, coverage.ok(불리언 true/false), decision(문자열 merge 또는 block)이다. failed 가 1 이상이거나 pct 가 threshold 미만이면 decision 은 block, 그 외에는 merge 여야 한다.
참고
- 요약 줄은 공백을 지운 뒤 검사되므로 등호 옆에 공백을 넣지 않는다:
passed=2 failed=0 skipped=0. - 중간 진행 상황을
passed=형태로 여러 번 찍으면 검사가 헷갈린다. 집계 줄은 마지막에 한 번만 출력한다. - 채점이 만드는 테스트 파일에는 실행 권한이 없다.
"$f"로 직접 실행하면 전부 실패로 집계된다. - 커버리지 비교에 셸 정수 연산을 쓰면 소수점이 잘려 경계에서 틀린다.
awk로 실수 비교를 하자. - 흔한 실수: 첫 실패에서 러너가 죽어 나머지를 못 세기, 격리된 테스트를 failed 로 세기, decision 을 손으로 적어 수치와 어긋나게 두기.
단계 8개
- 테스트 러너 만들기
- 실패해도 끝까지 세기
- 빈 입력에서도 안전하게
- 커버리지 임계값 게이트
- 상한이 있는 재시도
- 불안정한 테스트 격리
- 복합 게이트
- 판정과 수치가 일치하는 리포트