PEP 462 – CPython 핵심 개발 워크플로 자동화
- Author:
- Alyssa Coghlan <ncoghlan at gmail.com>
- Status:
- Withdrawn
- Type:
- Process
- Requires:
- 474
- Created:
- 23-Jan-2014
- Post-History:
- 25-Jan-2014, 27-Jan-2014, 01-Feb-2015
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 현재 핵심 개발 팀이 CPython에 변경 사항을 반영하기 위해 수행해야 하는 지루하고 시간이 많이 드는 여러 작업의 자동화에 투자할 것을 제안합니다. 이 제안은 코어 개발자가 CPython에 기여하는 데 쓸 수 있는 시간을 더 효과적으로 사용할 수 있도록 하는 것을 목표로 하며, 이는 자신의 변경 사항을 반영하기 위해 코어 팀에 의존하는 다른 기여자들의 경험도 개선하는 결과로 이어질 것입니다.
PEP 철회
이 PEP는 PEP 507의 GitLab 기반 제안을 위해 작성자에 의해 철회되었습니다.
다른 누군가가 이 PEP의 추진을 이어받고 싶다면 core-workflow 메일링 리스트로 연락하십시오.
핵심 개발 워크플로 변경의 근거
POSIX 시스템에서 새 기능을 CPython에 병합하는 현재의 코어 개발자 워크플로는 다음과 같이 “작동”합니다:
- 다른 사용자가 bugs.python.org에 제출한 변경 사항을 적용하는 경우, 먼저 그 사용자가 PSF 기여자 라이선스 동의서에 서명했는지 확인하십시오. 서명하지 않았다면, 변경 사항 병합을 계속하기 전에 서명을 요청하십시오.
- 메인 CPython 저장소의 현재 체크아웃에 변경 사항을 로컬로 적용합니다(변경 사항은 보통 먼저 bugs.python.org에서 패치로 논의되고 리뷰되지만, 현재 이 단계는 코어 개발자가 직접 작성한 변경 사항에 대해서는 필수로 간주되지 않습니다).
- 테스트 스위트를 로컬에서 실행하십시오. 최소한
make test또는./python -m test를 실행해야 합니다(시스템 사양에 따라 기본 구성에서는 몇 분이 걸리지만, 외부 네트워크 접근과 같은 모든 선택적 리소스를 활성화하면 훨씬 더 오래 걸립니다). make patchcheck를 실행하여 공백 문제를 수정하고, 필요할 수 있는 다른 변경 사항(Misc/ACKS 갱신이나 Misc/NEWS 항목 추가 등)을 상기하십시오.- 변경 사항을 커밋하고 메인 저장소에 푸시하십시오. hg가 원격 저장소에 새 헤드가 생성될 것이라고 알리면,
hg pull --rebase(또는 이에 상응하는 명령)를 실행하십시오. 이론적으로는 이 시점에 테스트를 다시 실행해야 하지만, 그 단계를 건너뛰고 싶은 유혹이 매우 큽니다. - 푸시한 후에는 변경 사항으로 인해 새로 발생한 실패가 없는지 안정 빌드봇을 모니터링하십시오. 특히 POSIX 시스템의 개발자는 Windows 빌드봇을 망가뜨리는 경우가 많으며, 그 반대도 마찬가지입니다. 드물게는 Linux나 Mac OS X의 개발자가 다른 POSIX 시스템을 망가뜨릴 수도 있습니다.
Windows에서 필요한 단계도 비슷하지만, 사용하는 정확한 명령은 다릅니다.
버그 수정 워크플로는 더 간단하기는커녕 새 기능 워크플로보다 더 복잡합니다! 새 기능은 default 브랜치에만 적용된다는 장점이 있지만, 버그 수정은 유지보수 브랜치에 포함할지도 함께 검토해야 합니다.
- 버그 수정이 Python 2.7에 해당하는 경우, Mercurial에서 독립적인 헤드로 유지되는 2.7 브랜치에도 별도로 적용됩니다.
- 버그 수정이 현재 3.x 유지보수 릴리스에 해당하는 경우, 먼저 유지보수 브랜치에 적용된 다음 default 브랜치로 순방향 병합됩니다. 두 브랜치는 동시에 hg.python.org에 푸시됩니다.
문서 패치는 기능 패치보다 간단하지만 아주 크게 간단하지는 않습니다. 주된 이점은 테스트 스위트를 실행하는 대신 문서가 성공적으로 빌드되는지만 확인하면 된다는 점입니다.
모든 것이 순조롭게 진행되더라도, 깔끔하게 적용되는 버그 수정 패치 하나를 커밋하는 데 저는 여전히 최소 20~30분이 걸린다고 추정합니다. 이러한 작업 중 여러 가지를 자동화할 수 있을 것이라는 점을 고려하면, 저는 현재의 관행이 부족한 코어 개발자 자원을 효과적으로 활용하고 있다고 생각하지 않습니다.
현재의 워크플로에는 매우 많은 불편함이 따르며, 이는 바람직하지 않은 몇몇 개발 관행으로 곧바로 이어집니다.
- 이러한 오버헤드의 상당 부분은 적용하는 패치마다 발생합니다. 이 때문에 작고 독립적인 변경보다는 큰 커밋을 선호하게 됩니다. 500줄짜리 기능을 커밋하는 데 필요한 시간은 1줄짜리 버그 수정을 커밋하는 데 필요한 시간과 사실상 같습니다. 더 큰 변경에 필요한 추가 시간은 커밋 과정이 아니라 그에 앞선 리뷰에서 발생합니다.
- 버그 수정을 적용하는 작업에 드는 추가 오버헤드는 대신 새 기능을 작업하려는 유인을 더 만들어 냅니다. 새 기능은 이미 본질적으로 더 흥미로운 작업이므로, 워크플로의 어려움까지 거들어 줄 필요는 없습니다!
- bugs.python.org에서 사전 리뷰를 받는 것은 추가 작업이므로, 변경을 곧바로 커밋하려는 유인이 생기고 python-checkins 메일링 리스트에서의 사후 리뷰에 대한 의존도가 높아집니다.
- 트래커에 올라온 패치가 완전하고 올바르며 병합할 준비가 되어 있더라도, 병합하는 데 시간을 들일 수 있는 코어 개발자를 기다리며 오랫동안 방치될 수 있습니다.
- 푸시 경쟁의 위험(특히 병합된 버그 수정을 푸시할 때)은 전체 로컬 테스트 실행을 건너뛰고 싶은 유혹을 만들어 내며(특히 이미 한 번 푸시 경쟁을 겪은 후에는), 이는 buildbot을 망가뜨릴 가능성을 높입니다.
- 빌드봇은 때때로 오랫동안 빨간색 상태로 남아 있어 로컬 테스트 실행에 오류를 끌어들이며, 이 때문에 패치가 크로스 플랫폼 문제를 일으켰는지를 판단하는 신뢰할 수 있는 지표 역할을 하지 못하기도 합니다.
- 콘퍼런스 이후의 개발 스프린트는 푸시 경쟁의 수렁에 빠져 버리기 때문에 악몽과 같습니다. 스프린트가 끝날 때까지 패치를 트래커에 그냥 남겨 두었다가 나중에 정리하고 싶은 유혹이 듭니다.
또한 Mercurial 브랜치를 관리하는 과정에서나, 곧바로 고칠 수 없는 상황에서 빌드봇을 망가뜨리는 경우 등, 코어 개발자가 다른 사람에게 불편을 끼치는 실수를 저지를 기회는 매우 많습니다. 이 때문에 기존 코어 개발 팀은 새 개발자에게 커밋 권한을 부여하는 데 신중해지고, 새 개발자들 역시 늘어난 권한을 실제로 사용하는 데 신중해집니다.
또한 (NEWS 파일을 최신 상태로 유지하는 것과 같은) 부수적인 성가신 문제들도 있으며, 이 역시 이 제안의 일부로서 반드시 다루게 됩니다.
자원봉사자가 이끄는 오픈 소스 프로젝트의 가장 중요한 자원 중 하나는 기여자들의 정서적 에너지입니다. 변경을 반영하는 현재의 방식은 그 측면에서 누구에게도 좋은 점수를 받지 못합니다:
- 코어 개발자에게 버그 수정을 위한 브랜치 관리는 까다롭고 실수하기 쉽습니다. NEWS 파일의 충돌과 변경 사항을 업로드하려 할 때의 푸시 경쟁은, 우리 대부분이 시간을 들이는 대가로 돈을 받지 않는 일에 짜증을 더합니다(그리고 돈을 받는 사람들에게도 CPython에 기여하는 것은 여러 책임 중 하나에 불과할 가능성이 높습니다). 변경을 실제로 병합하는 데 쓰는 시간은 추가 변경을 코딩하거나, 문서를 작성하거나 갱신하거나, 다른 사람의 기여를 리뷰하는 데 쓰지 못하는 시간입니다.
- 빨간색 빌드봇은 다른 개발자(로컬 테스트 실패가 그 개발자가 한 일 때문이 아닐 수도 있으므로), 릴리스 관리자(릴리스 전에 테스트 실패를 정리하기 위해 도움을 요청해야 할 수도 있으므로), 그리고 개발자 자신(우리가 무심코 일으킨 실패를 더 편한 때가 아니라 바로 지금 고쳐야 한다는 상당한 압박을 주며,
hg annotate만으로 새 실패의 원인을 찾기에 충분하지 않을 때hg bisect를 사용하기 더 어렵게 만들 수도 있으므로) 모두를 힘들게 합니다. - 다른 기여자 입장에서 보면, 변경을 실제로 병합하는 데 시간을 쓰는 코어 개발자는 이슈 트래커에서 패치를 리뷰하고 논의하거나, 다른 사람이 효과적으로 기여하도록 돕고 있지 않은 개발자입니다. 이는 프로젝트의 CI 시스템에서 이미 자동으로 테스트된 풀 리퀘스트에서 개발자가 “Merge” 버튼만 누르면 되는 단순함(GitHub나 BitBucket 같은 사이트에서 흔한 워크플로입니다)이나, 병합 과정 중 사후 리뷰 부분이 완전히 자동화된 방식(OpenStack의 경우처럼)에 익숙한 기여자에게 특히 답답한 일입니다.
현재 도구
현재 CPython 코어 개발 워크플로의 여러 부분을 관리하는 데 다음 도구들이 사용되고 있습니다.
- 버전 관리를 위한 Mercurial (hg.python.org)
- 이슈 추적을 위한 Roundup (bugs.python.org)
- 코드 리뷰를 위한 Rietveld (역시 bugs.python.org에서 호스팅됨)
- 자동화된 테스트를 위한 Buildbot (buildbot.python.org)
이 제안은 코드 리뷰에 Rietveld를 사용하는 대신, PEP 474에서 제안된, 더 많은 기능을 갖춘 Kallithea 기반의 forge.python.org 서비스를 사용할 것을 제안합니다. Guido는 원래의 Rietveld 구현이 주로 Google App Engine을 위한 공개 시연용 애플리케이션으로 의도된 것이라고 밝힌 바 있으며, Kallithea로 전환하면 Roundup의 패치 파일과 통합된 Rietveld 인스턴스의 관련 리뷰를 다룰 때 발생하는, 의도한 대상 브랜치를 식별하는 문제의 일부를 해결할 수 있습니다.
또한 워크플로의 더 많은 부분을 자동화하기 위해 새 도구를 추가하고, 나머지 도구들을 비판적으로 검토하여 교체 후보가 될 만한 것이 있는지 살펴볼 것을 제안합니다.
제안
이 제안의 핵심은 CPython이 OpenStack 프로젝트에서 사용하는 것과 유사한 “코어 리뷰어” 개발 모델을 채택하는 것을 목표로 삼아야 한다는 것입니다.
CPython 코어 개발 팀이 겪는 워크플로 문제는 이 팀만의 문제가 아닙니다. OpenStack 인프라 팀은 다음을 보장하도록 잘 설계된 자동화 워크플로를 고안했습니다:
- 패치가 리뷰된 뒤에는 병합 전에 자동화된 테스트가 실패하는 경우에만 개발자가 추가로 관여하면 됩니다
- 패치는 브랜치의 현재 상태를 기준으로 테스트되지 않고는 절대 병합되지 않습니다
- 주 개발 브랜치는 항상 녹색(정상) 상태를 유지합니다. 자동화된 테스트를 통과하지 못한 패치는 병합되지 않습니다
코어 개발자가 병합 전에 패치를 조금 수정하고 싶다면, 소스 코드 저장소에 직접 푸시하는 대신 리뷰 도구에서 패치를 내려받아 수정한 뒤 리뷰 도구에 다시 업로드합니다.
이 워크플로의 핵심은 Zuul이라는 도구로 구현되어 있습니다. Zuul은 OpenStack 프로젝트를 위해 특별히 만들어진 Python 웹 서비스이지만, 다른 코드 리뷰 시스템, 이슈 트래커, CI 시스템에 더 쉽게 적용할 수 있도록 플러그인 기반의 트리거 및 액션 시스템을 갖추도록 의도적으로 설계되었습니다. OpenStack 인프라 팀의 James Blair는 linux.conf.au 2014에서 Zuul에 대한 훌륭한 개요를 발표했습니다.
Zuul은 OpenStack을 위해 여러 워크플로를 처리하지만, 이 PEP에서 특히 관심을 두는 것은 “병합 게이팅(merge gating)” 워크플로입니다.
이 워크플로에서 Zuul은 Gerrit 코드 리뷰 시스템을 모니터링하여 “Approved”로 표시된 패치를 찾도록 구성되어 있습니다. Zuul은 그러한 패치를 발견하면 이를 가져와 “병합 후보(candidate merges)” 큐에 합칩니다. 그런 다음 Jenkins에서 병렬로 실행되는 테스트 실행 파이프라인을 만들고(전체 테스트 실행에 한 시간 가까이 걸리는 상황에서 하루에 24개보다 많은 커밋을 허용하기 위함입니다), 테스트를 통과하는 대로(그리고 큐에서 앞에 있는 모든 병합 후보가 통과하는 대로) 병합합니다. 패치가 테스트에 실패하면 Zuul은 해당 패치를 큐에서 빼내고, 큐에서 그 패치 뒤에 있는 모든 테스트 실행을 취소한 뒤, 실패한 패치를 제외하고 큐를 다시 구성합니다.
개발자가 병합 중에 실패한 테스트를 살펴보고 그것이 간헐적인 실패 때문이었다고 판단하면, 병합을 다시 시도하도록 패치를 재제출할 수 있습니다.
이 프로세스를 CPython에 맞게 적용하려면, Zuul이 Kallithea에서 승인된 풀 리퀘스트를 모니터링하게 하고(Kallithea에 기능 추가가 필요할 수 있습니다), 이를 Buildbot에 제출하여 안정 buildbot들에서 테스트한 다음, Mercurial에서 변경 사항을 적절히 병합하도록 하는 것이 가능할 것입니다. 이 아이디어에는 몇 가지 기술적 과제가 있으며, 이에 대해서는 아래에 별도의 절을 두었습니다.
CPython의 경우, Zuul의 테스트 병렬 실행 기능을 활용할 필요는 없을 것이라고 생각합니다(적어도 초기 단계에서는 확실히 그렇습니다. 패치를 리뷰하고 승인하는 데 필요한 인력을 확보하는 것이 아니라 병합 게이팅 시스템의 순차적인 패치 테스트가 주된 병목이 되는 시점에 이른다면, 그날은 정말 좋은 날일 것입니다).
하지만 병합 큐 자체는 앞의 근거 절에서 설명한 여러 문제를 직접 해결할 수 있는 매우 강력한 개념입니다.
보류된 제안
OpenStack 팀은 다른 여러 활동을 조율하는 데에도 Zuul을 사용합니다:
- Gerrit에 게시된 패치에 대해 예비 “check” 테스트를 실행합니다.
- 변경 사항이 병합되면 갱신된 릴리스 산출물을 생성하고 문서를 다시 게시합니다
- 사용자가 직접 로그를 검색하도록 요구하는 대신, 스팸 필터와 함께 ElasticSearch를 사용하여 테스트 출력을 모니터링하고 테스트 실패의 원인이 되었을 수 있는 구체적인 간헐적 실패를 제시하는 Elastic recheck 기능
이러한 기능들은 앞으로 검토해 볼 가치가 있는 가능성이지만(그리고 OpenStack 인프라 팀과 더 긴밀한 협력을 추구할 때 얻을 수 있다고 보는 이점 중 하나이지만), 병합 게이팅이 제공하는 것으로 보이는 것과 같은 수준의 근본적인 워크플로 개선을 제공한다고 보지는 않습니다.
다만 게이트에서 간헐적인 테스트 실패로 인한 문제가 너무 많다고 판단되면, 초기 배포의 일부로 “Elastic recheck” 기능을 도입하는 것을 고려해야 할 수도 있습니다.
제안된 변형
Terry Reedy는 승인된 문서 전용 패치만을 골라내는 초기 필터를 두자고 제안했습니다(CPython의 열린 이슈 4000여 개 중 약 700개가 순수한 문서 업데이트입니다). 이 접근 방식은 불안정한 테스트 및 크로스 플랫폼 테스트와 관련된 여러 문제를 피하면서도, 나머지 자동화 흐름(예를 들어 패치를 병합 큐에 넣는 방법)을 정립할 수 있게 해 줍니다.
이 접근 방식의 주요 단점은 Zuul이 보통 기대하는 것처럼 병합 프로세스를 완전히 제어하지 못한다는 점이며, 따라서 이와 관련하여 추가적인 조율이 필요할 수 있습니다.
초기 배포에서 테스트 신뢰성 문제가 예상보다 많은 것으로 드러날 경우를 대비하여, 이 접근 방식을 대체 방안으로 남겨 두는 것이 좋을 수 있습니다.
또한 패치가 “Docs” 트리 바깥의 파일을 전혀 수정하지 않았음을 감지하면 테스트 스위트를 실행하지 않고, 대신 문서가 오류 없이 빌드되는지만 확인하도록 병합 게이팅 기준을 조정하는 것도 가능합니다.
또 다른 대안으로, 문서의 일부(튜토리얼과 HOWTO 가이드 등)를 주 소스 저장소 밖으로 옮기고 PEP 474에서 설명하는 더 단순한 풀 리퀘스트 기반 모델로 관리하는 것도 합리적일 수 있습니다.
기대되는 이점
이 제안의 이점은 코어 개발 팀에 가장 직접적으로 돌아갑니다. 무엇보다도, 업데이트된 코드 리뷰 시스템에서 패치를 “Approved”로 표시하고 나면 대개 할 일이 끝난다는 뜻입니다. 실제로 패치를 적용하고, 테스트를 실행하고, Mercurial에 병합하는 데 드는 추가적인 20~30분(또는 그 이상)의 작업은 모두 Zuul이 조율하게 됩니다. 푸시 경쟁 또한 과거의 일이 될 것입니다. 스프린트에서 많은 코어 개발자가 패치를 승인하고 있다면, 그것은 개발자들이 변경 사항을 병합하려다 실패하여 좌절하는 대신 단지 Zuul의 큐가 더 길어진다는 것을 의미할 뿐입니다. 테스트 실패는 여전히 발생하겠지만, 그 결과는 주 저장소의 코드가 깨지는 것이 아니라 해당 패치가 병합 큐에서 제거되는 것입니다.
시간 투자의 대부분이 리뷰 과정으로 옮겨가므로, 이는 “리뷰하기 쉬운 개발”, 즉 더 작고 리뷰하기 쉬운 패치를 장려하기도 합니다. 테스트를 여러 번 실행하는 오버헤드를 코어 개발자가 아닌 Zuul이 부담하게 되기 때문입니다.
하지만 코어 개발 팀에서 이렇게 시간을 잡아먹는 일을 없애면 다른 기여자들의 CPython 개발 경험도 개선될 것입니다. 패치가 “흐지부지 잊히는” 여러 경우를 없애 줄 뿐만 아니라, 코어 개발자가 기여된 패치를 리뷰하는 데 쓸 수 있는 시간도 늘려 주기 때문입니다.
다른 기여자들에게 돌아가는 이점의 또 다른 예로, 주로 새 기여자를 대상으로 하는 스프린트가 코어 개발자 단 한 명만 참석한 채로 진행될 때(지난 몇 년간 PyCon AU의 스프린트처럼), 병합 큐가 있으면 그 개발자는 패치를 리뷰하고 스프린트의 다른 기여자들을 돕는 데 더 많은 시간을 쏟을 수 있습니다. 패치를 포함하도록 수락하는 일이 현재처럼 비교적 시간이 많이 드는 과정이 아니라 Kallithea UI에서 한 번의 클릭으로 끝나기 때문입니다. 여러 코어 개발자가 참석한 경우라도, 컴퓨터가 처리할 수 있을 (그리고 처리해야 할) 만큼 기계적인 일보다는 다른 스프린트 참가자들과 교류하는 데 시간과 노력을 쓸 수 있게 하는 편이 더 낫습니다.
변경 사항을 커밋할 때 실수할 수 있는 경우 대부분이 자동화로 사라지므로, 기여자가 코어 개발자로 지명될 때 새로 배워야 할 것도 상당히 줄어듭니다. 이는 기존 코어 개발자들이 그러한 추가 책임을 더 편하게 부여할 수 있게 하고, 새 기여자들이 그 책임을 더 편하게 행사할 수 있게 한다는 이중의 이점이 있을 것입니다.
마지막으로, CPython의 기본 브랜치가 더 안정적이면 다른 Python 프로젝트들이 새 릴리스의 릴리스 후보 단계에 들어갈 때까지 기다릴 필요 없이 주 저장소를 대상으로 직접 지속적 통합을 수행하기가 더 쉬워집니다. 현재로서는 그러한 시스템을 구축하는 것이 그다지 매력적이지 않습니다. CPython 자체의 Buildbot 군이 빌드가 사용 가능한 상태임을 알릴 때까지 기다리는 추가 메커니즘을 포함해야 하기 때문입니다. 제안된 병합 게이팅 시스템을 사용하면 트렁크는 항상 사용 가능한 상태로 유지됩니다.
기술적 과제
Zuul을 OpenStack 인프라에서 CPython 인프라로 옮겨 적용하려면 적어도 추가적인 Zuul 트리거 및 액션 플러그인을 개발해야 하며, 기존 도구 일부에 대한 추가 개발이 필요할 수도 있습니다.
Kallithea 대 Gerrit
Kallithea에는 현재 Gerrit의 것과 동등한 투표/승인 기능이 없습니다. CPython에는 Gerrit의 투표 시스템만큼 정교한 것은 필요하지 않습니다. Zuul의 동작을 트리거하는, 코어 개발자만 사용할 수 있는 단순한 “Approved” 표시면 충분할 것입니다. 코어 개발자인지 여부를 나타내는 플래그는 Roundup에서 사용할 수 있으며, 패치 업로더가 PSF 기여자 라이선스 동의서에 서명했는지 여부를 나타내는 플래그도 마찬가지입니다. 다만 Kallithea 인스턴스와 Roundup 사이에서 기여자 계정을 연결하려면 추가 개발이 필요할 수 있습니다.
기존 Zuul 트리거 중 일부는 특정 댓글을 감시하는 방식으로 동작합니다(특히, 관련 없는 간헐적 실패로 이전에 거부된 변경 사항의 병합을 Zuul에 다시 시도하도록 요청하는 recheck/reverify 댓글). Kallithea에도 이와 비슷한 명시적 트리거가 필요할 가능성이 높습니다.
현재 Gerrit용 Zuul 플러그인은 Gerrit 활동 스트림에서 특정 이벤트를 감시하는 방식으로 동작합니다. Kallithea에 이에 상응하는 기능이 없다면, 트리거로 삼고자 하는 이벤트에 적합한 무언가를 추가해야 합니다.
Gerrit 대신 Kallithea의 활동을 감시하는 Zuul 플러그인을 만드는 개발 작업도 필요합니다.
Mercurial 대 Gerrit/git
Gerrit은 패치의 실제 저장 메커니즘으로 git을 사용하며, 승인된 패치의 병합을 자동으로 처리합니다. 이와 달리 Kallithea는 특정 DVCS 구현(현재 Mercurial과 git 백엔드를 사용할 수 있음) 위의 추상화 계층으로 RhodeCode가 만든 vcs 라이브러리를 사용합니다.
Zuul은 패치 조작을 위해 git과도 직접 통합되어 있습니다. 제가 아는 한, 설계의 이 부분은 현재 플러그인 방식으로 교체할 수 없습니다. 하지만 PyCon US 2014 스프린트에 참석한 Mercurial 코어 개발자들은 git뿐만 아니라 Mercurial에서도 Zuul을 사용할 수 있도록 코어 개발 팀 및 Zuul 개발자들과 협력하는 데 관심을 보였습니다. Zuul 자체가 Python 애플리케이션이므로, RhodeCode 및 Kallithea와 동일한 DVCS 추상화 라이브러리를 사용하도록 Zuul을 이전하는 것이 이를 달성하기 위한 실행 가능한 방법일 수 있습니다.
Buildbot 대 Jenkins
CI 시스템과 Zuul의 상호 작용 역시 플러그인 방식으로 교체할 수 있으며, Gearman을 선호하는 인터페이스로 사용합니다. 따라서 CI 작업을 Jenkins가 아닌 Buildbot에서 실행하도록 조정하는 일은 Zuul의 요청을 처리하여 Buildbot 마스터에 전달할 수 있는 Gearman 클라이언트를 작성하기만 하면 되는 문제일 것입니다. Zuul은 Gearman과 통신하기 위해 순수 Python으로 작성된 gear 클라이언트 라이브러리를 사용하며, 이 라이브러리는 Buildbot 쪽을 처리하는 데에도 유용할 것입니다.
초기 단계에서는 테스트 실행을 파이프라인화하려고 시도하지 않을 것을 제안한다는 점에 유의하십시오. 이는 Zuul이 여러 패치를 병렬로 테스트할 수도 있는 방식이 아니라, 병합 큐의 맨 앞에 있는 패치만 Buildbot 군에서 테스트되는 매우 단순한 모드로 실행된다는 것을 의미합니다. 저는 Buildbot 마스터에 강제 빌드를 요청한 다음, 큐의 두 번째 패치로 넘어가기 전에 결과가 돌아오기를 기다리는 것과 동등한 방식을 구상하고 있습니다.
결국 이것으로 충분하지 않다고 판단하여 Zuul의 CI 파이프라인 기능을 사용하기 시작해야 한다면, 현재처럼 자원봉사자가 유지 관리하는 정적으로 프로비저닝된 시스템에 의존하는 대신 테스트 실행을 동적으로 프로비저닝되는 클라우드 이미지로 옮기는 방안을 검토해야 할 수도 있습니다. OpenStack CI 인프라 팀은 현재 사용 중인 Jenkins 마스터를 더 단순한 순수 Python 테스트 실행기로 대체하는 아이디어를 모색하고 있으므로, Buildbot이 파이프라인 테스트 모델을 효과적으로 지원하도록 만들 수 없다고 판단되면 CPython용 Jenkins 인스턴스를 구축하기보다는 그 작업에 참여할 가능성이 높습니다.
이 경우 주요 기술적 위험은 Linux 이외의 플랫폼에서의 테스트를 확실히 지원하는 문제일 것입니다(현재 안정 buildbot들은 몇 가지 서로 다른 Linux 변형 외에도 Windows, Mac OS X, FreeBSD, OpenIndiana를 다루고 있기 때문입니다).
이러한 시나리오에서도 Buildbot 플릿은 병합 게이팅 과정에 관여하지 않더라도 마스터 저장소를 대상으로 (주기적으로 또는 모든 커밋마다) “check” 실행을 수행하는 역할을 여전히 맡게 될 것입니다. 더 특이한 구성(스레드 없이 빌드하거나 SSL/TLS 지원 없이 빌드하는 경우 등)은 게이트 기준에 포함되기보다는 (적어도 처음에는) 여전히 그런 방식으로 처리될 가능성이 높습니다.
유지 보수 브랜치 처리
OpenStack 프로젝트는 유지 보수 브랜치 문제를 직접 다루기보다는 대체로 다운스트림 벤더에게 맡깁니다. 이는 우리의 유지 보수 브랜치를 처리하도록 Zuul을 어떻게 조정할 것인지에 관해 답해야 할 질문들이 있다는 뜻입니다.
Python 2.7은 별도의 패치 큐로 취급하면 충분히 쉽게 처리할 수 있습니다. 이는 Kallithea에서 Python 2.7 유지 보수 브랜치를 갱신하기 위해 별도의 풀 리퀘스트를 제출하는 방식으로 자연스럽게 처리될 것입니다.
Python 3.x 유지 보수 브랜치는 잠재적으로 더 복잡합니다. 현재 제 권고는 이 브랜치들을 관리하는 데 Mercurial 병합을 사용하는 것을 그냥 중단하고, 대신 Python 2.7 브랜치와 마찬가지로 독립적인 헤드로 취급하는 것입니다. 활성 Python 3 유지 보수 브랜치와 기본 개발 브랜치에 대해 각각 별도의 풀 리퀘스트를 제출해야 할 것입니다. 이 접근 방식의 단점은 수정 사항이 기본 브랜치에는 제출되지 않고 유지 보수 브랜치에만 병합될 위험이 커진다는 점입니다. 따라서 모든 유지 보수 브랜치 풀 리퀘스트가 병합 전에 대응하는 기본 브랜치 풀 리퀘스트를 갖추거나, 그렇지 않으면 해당 브랜치에만 적용되며 이후 브랜치로 포팅할 필요가 없다는 명시적인 고지를 포함하도록 보장하는 추가 도구를 설계하는 것이 좋을 수 있습니다.
이러한 접근 방식에는 활성 Python 3 유지 보수 브랜치가 두 개 존재하는 간헐적인 기간에도 비교적 깔끔하게 적응할 수 있다는 이점이 있습니다.
이 문제는 Kallithea에 대한 몇 가지 잠재적인 사용자 인터페이스 아이디어를 시사합니다. 예를 들어 풀 리퀘스트를 두 번째 브랜치에 적용할 수 있도록 풀 리퀘스트를 복제하는 기능이 바람직할 수 있습니다.
보안 브랜치 처리
단순함을 위해, 보안 수정 전용 브랜치의 처리는 그대로 두기를 제안합니다. 해당 브랜치의 릴리스 관리자들은 계속해서 특정 변경 사항을 수동으로 백포트할 것입니다. 유일한 변화는, 병합하기 전에 다른 사람들이 업데이트를 검토해 주기를 원한다면 Kallithea 풀 리퀘스트 워크플로를 사용하여 백포트를 수행할 수 있게 된다는 점입니다.
NEWS 파일 갱신 처리
NEWS 파일 갱신을 처리하는 현재 방식은 활성 유지 보수 브랜치의 버그 수정을 이후 브랜치로 병합할 때 불필요한 충돌을 자주 일으킵니다.
Issue #18967*에서는 이 영역에서 가능한 몇 가지 개선 사항을 논의하고 있으며, 이는 Zuul을 워크플로 자동화 도구로 채택하는지와 관계없이 유익할 것입니다.
“stable” Buildbot 슬레이브의 안정성
이 제안에서는 명목상 안정적인 buildbot의 불안정성이 훨씬 더 큰 영향을 미칩니다. 개발 브랜치로의 병합을 통제하는 각 시스템에 대해 우리가 진정으로 만족하는지 확인해야 하며, 그렇지 않다면 해당 시스템을 “unstable” 상태로 옮겨야 합니다.
간헐적인 테스트 실패
일부 테스트, 특히 타이밍 테스트는 기존 Buildbot 플릿에서 간헐적으로 실패합니다. 특히 VM으로 실행되는 테스트 시스템은 VM 호스트의 부하가 평소보다 높을 때 때때로 타이밍 실패를 보일 수 있습니다.
OpenStack CI 인프라에는 간헐적인 실패에 대처하는 데 도움이 되는 여러 추가 기능이 포함되어 있습니다. 그중 가장 기본적인 것은 원래의 실패가 알려진 간헐적 실패(그 간헐적 실패가 OpenStack 자체에 있는 것이든 단지 불안정한 테스트에 있는 것이든)로 인한 것으로 보일 때 개발자가 패치 병합을 다시 시도하도록 요청할 수 있게 하는 것입니다.
더 정교한 Elastic recheck 기능도 고려해 볼 만합니다. 특히 CPython 테스트 스위트의 출력은 OpenStack의 더 복잡한 다중 서비스 테스트의 출력보다 훨씬 단순하므로, 자동화된 분석에 한층 더 적합할 가능성이 높기 때문입니다.
사용자 정의 Mercurial 클라이언트 워크플로 지원
OpenStack 워크플로의 유용한 부분 중 하나는 “git review” 플러그인으로, 로컬 git 클론의 브랜치를 리뷰를 위해 Gerrit으로 비교적 쉽게 푸시할 수 있게 해 줍니다.
PEP 474에서는 기존 CPython 핵심 개발 워크플로의 일부 측면을 자동화하는 사용자 정의 Mercurial 확장 초안을 언급합니다.
이 제안의 일환으로, 해당 사용자 정의 확장은 기존의 Roundup/Rietveld 기반 리뷰 워크플로뿐만 아니라 새로운 Kallithea 기반 리뷰 워크플로에서도 동작하도록 확장될 것입니다.
사회적 과제
여기서 주된 사회적 과제는 핵심 개발 팀이 자신들의 관행을 바꾸도록 하는 것입니다. 그러나 이 제안으로 자동화되는, 번거롭지만 필요한 단계들은 기존 개발자들이 이 아이디어에 동참할 강한 동기를 만들어 낼 것입니다.
기존 개발자들에게 이 워크플로의 자동화에 단점이 없음을 확신시키려면 다음 세 가지 구체적인 기능이 필요할 수 있다고 생각합니다.
- 패치를 반영하는 데 코어 개발자 한 명의 승인만 요구합니다. 이는 향후 재검토될 수 있지만, 초기 도입 시에는 현상을 유지해야 합니다.
- 릴리스의 릴리스 후보 단계를 제외하고는 코어 개발자가 자신의 패치를 자유롭게 승인할 수 있음을 명시적으로 밝힙니다. 이는 향후 재검토될 수 있지만, 초기 도입 시에는 현상을 유지해야 합니다.
- 최소한 릴리스 관리자에게는 특정 패치를 병합 큐의 맨 앞으로 강제로 보낼 수 있는 “지금 병합” 기능이 있도록 보장합니다. 이 목적에는 릴리스 준비용으로 별도의 클론을 사용하는 것으로 충분할 수 있습니다. 장기적으로는 자동 병합 게이팅 덕분에 릴리스 산출물 준비도 더 많이 자동화할 수 있을 것입니다.
현실적 과제
PSF가 직간접적으로 후원받는 자체 워크플로 인프라를 운영하는 주된 이유는, 일반 대중에게 무료로 제공되는 인프라의 성능이 용납할 수 없을 만큼 낮고 유연성이 부족했던 과거의 경험 때문입니다. CPython 개발은 원래 SourceForge에서 호스팅되었습니다. SF가 Subversion 지원 제공에 더디고 CVS 성능 문제까지 겪자 소스 관리는 자체 호스팅으로 옮겨졌고(PEP 347 참조), 이슈 추적은 이후 당시 SF의 성능 문제와 SF 트래커의 전반적인 사용성 문제가 겹쳐 (Upfront Systems가 후원하는) 전용 호스팅 위의 오픈 소스 Roundup 이슈 트래커로 옮겨졌습니다(새 트래커 선정의 결과와 과정은 PEP가 아니라 python.org 위키에 기록되었습니다).
따라서 “SourceForge 사용성 및 안정성 문제, 2라운드”를 자초하는 제안은 CPython 핵심 개발 팀의 적어도 일부 구성원(이 PEP의 저자를 포함하여)으로부터 상당한 반대에 부딪힐 것입니다. 이 제안은 후원받거나 PSF가 자금을 대는 인프라로 자체 호스팅할 수 있으면서 CPython 핵심 개발 팀의 요구에 맞게 사용자 정의할 수 있는 오픈 소스 Python 프로젝트인 도구만을 권장함으로써 그러한 역사를 존중합니다.
그러나 이 제안이 (채택된다면) 성공하려면, 필요한 구성, 사용자 정의, 통합 및 배포 작업을 어떻게 수행할지 파악해야 합니다.
CPython 지원 인프라에 새로운 요소(speed.python.org)를 추가하려던 마지막 시도는 안타깝게도 실패했는데, 이는 관련된 코어 개발자와 PSF 이사회 구성원들에게 프로젝트를 추진할 시간이 부족했고, 다른 누군가가 이 활동을 이끌 수 있도록 필요한 내용을 파악하게 하는 데 어려움이 있었기 때문입니다(HP가 해당 프로젝트에 기증한 하드웨어는 현재 대신 PyPy를 지원하는 데 사용되고 있지만, 이 상황은 시간을 써야 할 우선순위 높은 일이 많은 자원봉사자의 노동에 의존하여 프로젝트를 완수하는 것이 얼마나 어려운지를 잘 보여 줍니다).
CVS에서 Subversion으로, 그리고 Subversion에서 Mercurial로의 소스 관리 이전, SourceForge에서 Roundup으로의 이슈 트래커 이전, Roundup과 Rietveld 간의 코드 리뷰 통합, Buildbot 지속적 통합 플릿의 도입처럼 결국 성공한 과거 프로젝트들조차도, 자원봉사자들이 관련된 수많은 기술적·사회적 과제를 헤쳐 나가는 동안 오랜 시간이 걸렸습니다.
다행히 이 제안과 PEP 474의 여러 측면이 Red Hat의 Beaker 오픈 소스 하드웨어 통합 테스트 시스템 및 기타 업무 관련 프로젝트에서 검토 중인 다양한 워크플로 개선 사항과 맞아떨어지므로, 저는 매주 약 하루를 CPython 인프라 프로젝트 작업에 할애할 수 있도록 조치해 두었습니다.
Rackspace가 pypi.python.org 인프라 유지 관리에 이미 기여하고 있는 것과 더불어, 저는 개인적으로 이러한 방식이 CPython 재배포자와 주요 사용자 사이에 퍼진 좀 더 일반적인 인식을 보여 준다고 생각합니다. 곧 자원봉사 기여자가 여가 시간만으로 그 인프라를 전부 유지하기를 기대하거나 PSF를 통해 간접적으로 자금을 지원하기(그에 따르는 추가 관리 부담도 수반됩니다)보다는, 개발자 시간을 직접 기여하여 업스트림 인프라 유지를 돕는 것이 가치 있다는 인식입니다. 저는 이것을 긍정적인 추세로 보며, 제가 할 수 있는 한 계속 장려할 것입니다.
미해결 질문
사실상 이 PEP의 모든 것입니다. 병합 게이팅과 Zuul을 도입할 것입니까? 여러 기술적 과제를 어떻게 해결할 것입니까? Kallithea와 Zuul 개발 커뮤니티는 이 노력을 성공시키는 데 필요한 형태의 협업에 열려 있습니까?
제 업무 시간 일부를 이 일에 쓸 수 있도록 조정해 두었지만, 우리가 OpenStack 자체의 핵심 의존성이고, Zuul은 OpenStack 인프라 팀이 만든 것이며, 현재 OpenStack에 투입할 수 있는 개발 자원이 CPython보다 훨씬 많으므로, OpenStack 재단에 추가 지원을 요청할 것입니까?
Python 재배포자와 주요 사용자 쪽에서 일하는 다른 관심 있는 분들도 이 노력을 지원하는 데 개발자 시간을 투자하자는 사업적 근거를 상급자에게 제시할 수 있는 위치에 있습니까?
다음 단계
이 제안을 추진한다면, PEP 474의 Kallithea 기반 forge.python.org 제안에 뒤따르는 후속 프로젝트가 될 것입니다. 현재 진행 중인 논의, 검토, 개념 증명 파일럿 과정에 대한 자세한 내용은 해당 PEP를 참고하십시오.
감사의 글
이 제안의 예비 초안에 귀중한 피드백을 주신 Jesse Noller, Alex Gaynor, James Blair께 감사드리며, 첫 초안이 공개된 후 추가로 기술적 피드백을 주신 James와 Monty Taylor께도 감사드립니다.
PEP 474에 관한 논의를 함께해 주신 Bradley Kuhn, Mads Kiellerich를 비롯한 Kallithea 개발자 여러분께 감사드립니다. 이 논의 덕분에 이 제안은 리뷰 구성 요소로 기존 Rietveld 설치본 대신 Kallithea를 사용하는 방향으로 크게 개정되었습니다.
Copyright
This document has been placed in the public domain.