업무 도구에서 불편한 부분을 발견해도 우회해서 사용하는 경우가 많다. 같은 문제를 반복해서 겪은 뒤에는 직접 수정해 기여하기로 했다. 두 건 모두 작은 PR이지만 처음으로 외부 저장소에 병합된 코드였기에 과정을 정리했다.
첫 번째 — Argo Workflows 이벤트 플로우 아이콘
Argo Workflows UI에는 Event Flow라는 화면이 있다. 이벤트 소스와 센서의 연결을 다이어그램으로 보여 준다. 다른 소스는 모두 아이콘이 뜨는데 Bitbucket Server만 빈칸으로 나왔다. 우리가 Bitbucket Server를 쓰고 있어서 매번 눈에 거슬렸다.
코드를 확인해 보니 원인은 단순했다. 아이콘 매핑 테이블에 Bitbucket Server만 빠져 있었다.
// ui/src/app/event-flow/icons.ts
const icons = {
// ...
bitbucketserverEventSource: 'git', // 이 줄이 없었다
}
타입 정의에도 bitbucketserver를 추가했다. 실제로 바뀐 것은 세 줄, 추가 3줄·삭제 0줄이다.

3줄짜리 PR. 메인테이너가 'Thanks for tracking this down'이라고 남겨 줬다.
올린 지 하루 남짓 만에 머지됐다. 메인테이너가 Event Flow UI를 잘 아는 분께 한 번 더 봐 달라고 돌렸던 모양이다. 나는 동작 확인 스크린샷만 붙였는데 코드 세 줄치고는 과분하게 친절한 리뷰를 받았다.
두 번째 — Hera의 initContainers 빌드 로직
Hera는 Argo Workflow를 Python으로 작성하는 SDK다. init_containers에 Secret 참조를 추가했을 때 생성된 YAML이 Argo 스펙과 맞지 않았다. valueFrom.secretKeyRef 구조가 필요했지만 해당 값이 상위 필드에 잘못 배치됐다.
원인은 이랬다. 다른 컨테이너 필드는 모두 .build()를 거쳐 모델로 변환되는데 init_containers만 그 처리를 빠뜨리고 있었다. 그래서 변환 메서드를 하나 만들고, 그걸 쓰도록 호출부를 전부 교체했다.
def _build_init_containers(self) -> Optional[List[ModelUserContainer]]:
if self.init_containers is None:
return None
return [i.build() if isinstance(i, UserContainer) else i
for i in self.init_containers]
_mixins.py에 이 메서드를 넣고, container.py·dag.py·script.py·steps.py 등에서 init_containers=self.init_containers로 직접 넘기던 부분을 self._build_init_containers()로 바꿨다. 건드린 파일은 열세 개지만 대부분 한 줄짜리이고, 나머지는 예제와 문서다.
이건 올린 당일에 머지됐다. 리뷰어 두 명이 approve를 찍고 "Thank you 🚀" 한마디를 남겼다. 반나절 만이었다.
돌아보며
두 PR 모두 코드 자체는 별것 없다. 한쪽은 빠진 줄을 채웠고, 다른 한쪽은 이미 다른 곳에서 하던 처리를 한 군데만 빠뜨린 걸 맞췄다. 그런데 막상 올리려니 CONTRIBUTING을 읽고 DCO 사인오프를 맞추고 커밋 메시지 컨벤션을 확인하는 데서 시간이 더 걸렸다. 코드보다 그 주변이 더 일이었다.
회사 안에서만 코드를 쓰다 보면 내 코드가 닿는 범위도 사내로 제한된다. 남이 매일 쓰는 도구에 세 줄이 들어가는 건 조금 다른 경험이었다. 그 뒤로는 거슬리는 게 있으면 우회하기 전에 저장소부터 확인하는 습관이 생겼다.
참고