풀 리퀘스트의 수명 주기

소개

CPython은 풀 리퀘스트 기반 워크플로를 사용합니다. 즉, Git에서 브랜치를 만들고 변경 사항을 작성한 다음, 그 변경 사항을 GitHub에 있는 여러분의 포크(origin)에 푸시하고, 공식 CPython 저장소(upstream)를 대상으로 풀 리퀘스트를 생성한다는 뜻입니다.

요약 참고 자료는 풀 리퀘스트 생성 빠른 참조를 참고하십시오.

단계별 안내

이미 시스템을 설정하고, 소스 코드를 받고, Python을 빌드한 상태여야 합니다.

  • upstream 저장소에서 데이터를 갱신하십시오:

    git fetch upstream
    
  • 업스트림 저장소의 main 브랜치에서 로컬 클론에 새 브랜치를 만드십시오:

    git checkout -b <branch-name> upstream/main
    

    참고

    버그 수정을 포함한 Python의 거의 모든 변경 사항은 먼저 main 브랜치를 대상으로 작성해야 합니다. 자세한 내용은 여기를 참고하십시오.

  • 코드를 변경하고, git status와 git diff를 사용해 변경 사항을 확인하십시오.

    (좋은 PR 만들기에 대해 더 알아보기)

  • 변경 사항에 문제가 없고 테스트 실패를 일으키지 않는지 확인하십시오:

    make patchcheck
    ./python -m test
    

    (patchcheck와 테스트 실행과 작성에 대해 더 알아보기)

  • 변경 사항이 만족스러우면 파일을 추가하고 커밋하십시오:

    git add <filenames>
    git commit -m '<message>'
    

    (좋은 커밋 만들기에 대해 더 알아보기)

  • 코드가 린트 검사를 제대로 통과하지 못하면 pre-commit이 오류 메시지와 함께 커밋을 블록합니다. 예를 들면 다음과 같습니다:

    Doc/library/stdtypes.rst:5718: No newline at end of file. (missing-final-newline)
    
  • 모든 린트 오류를 수정했으면 작업 내용을 GitHub 포크에 푸시할 수 있습니다:

    git push origin <branch-name>
    
  • 마지막으로 https://github.com/<your-username>/cpython에 접속하십시오. 방금 푸시한 브랜치가 표시된 상자와 공식 CPython 저장소를 대상으로 풀 리퀘스트를 생성할 수 있는 녹색 버튼이 보일 것입니다.

  • 다른 사람들이 리뷰 코멘트를 달기 시작하면, 여러분의 브랜치로 전환하여 추가로 변경하고 커밋한 다음 푸시하는 방식으로 코멘트에 대응할 수 있으며, 이렇게 하면 PR이 자동으로 갱신됩니다:

    git switch <branch-name>
    # make changes and run tests
    git add <filenames>
    git commit -m '<message>'
    git push origin <branch-name>
    
    • PR을 리뷰하는 코어 팀 구성원이 여러분의 PR 브랜치에 하나 이상의 커밋을 푸시했다면, 브랜치를 체크아웃한 후 편집하기 전에 다음을 실행하십시오:

      git pull origin <branch-name>  # pull = fetch + merge
      

      포크에 푸시하지 않은 로컬 변경 사항이 있는 상태에서 병합 충돌이 발생하면, Git이 이를 경고하고 충돌 해결 모드로 진입합니다. 아래의 병합 충돌 해결하기를 참고하십시오.

  • 시간이 지나 main 브랜치와 병합 충돌이 발생하면, GitHub에 이를 알리는 경고가 표시되며 충돌을 해결하라는 요청을 받을 수 있습니다. 로컬에서 충돌을 해결하면서 main 브랜치의 변경 사항을 병합하십시오:

    git switch <branch-name>
    git pull upstream main  # pull = fetch + merge
    # resolve conflicts: see "Resolving Merge Conflicts" below
    git push origin <branch-name>
    
  • PR이 승인되어 병합되면 브랜치를 삭제할 수 있습니다:

    git branch -D <branch-name>  # delete local branch
    git push origin -d <branch-name>  # delete remote branch
    

병합 충돌 해결하기

서로 다른 브랜치(또는 서로 다른 저장소에 있는 한 브랜치의 변형들)의 변경 사항을 병합할 때, 두 브랜치에 하나 이상의 파일에 대해 서로 호환되지 않는 변경 사항이 있을 수 있습니다. 이를 “병합 충돌”이라고 하며, 다음과 같이 수동으로 해결해야 합니다:

  1. 병합 충돌이 있는 파일을 확인하십시오:

    git status
    
  2. 영향을 받은 파일을 편집하여 의도한 최종 상태로 만드십시오. Git이 삽입한 특수한 “충돌 마커”를 반드시 제거하십시오.

  3. 영향을 받은 파일을 커밋하십시오:

    git add <filenames>
    git merge --continue
    

마지막 명령을 실행할 때 Git이 커밋 메시지를 작성할 편집기를 열 수 있습니다. 보통은 그대로 두고 편집기를 닫아도 괜찮습니다.

자세한 기술적 설명은 merge 명령의 문서를 참조하십시오.

강제 푸시하지 마십시오

커밋 기록을 그대로 유지하려면 기록을 스쿼시하거나 수정한 다음 PR에 강제 푸시하는 일을 피하십시오. 리뷰어는 개별 커밋을 살펴보기를 원하는 경우가 많습니다.

CPython은 스쿼시 병합을 사용하므로 PR은 병합될 때 결국 하나의 커밋이 됩니다.

좋은 PR 만들기

제출할 풀 리퀘스트를 만들 때, 풀 리퀘스트가 수락되도록 하기 위해 해야 할 일이 몇 가지 있습니다.

  1. 올바른 Python 버전을 대상으로 변경하십시오. 일반적으로 모든 변경은 먼저 main 브랜치를 대상으로 이루어집니다. 버그 수정도 마찬가지입니다. 변경이 그곳에 병합된 후에는 이전 유지보수 릴리스로도 백포트됩니다. 이렇게 해서 영향을 받는 모든 버전이 처리되도록 보장합니다. 따라서 유지 보수 브랜치를 기반으로 새 변경을 직접 만드는 것은 특정한 경우에만 사용됩니다. 예를 들어 해당 변경이 main에 적용되지 않거나, 이전 Python 버전에서 main과 다른 접근 방식이 필요한 경우입니다.

  2. Python의 스타일 지침을 반드시 따르십시오. Python 코드는 PEP 8을, C 코드는 PEP 7을 따라야 합니다. 한두 군데 어긋나는 부분이 있다면 풀 리퀘스트를 병합하는 코어 팀 구성원이 수정할 수 있습니다. 하지만 스타일 가이드에서 체계적으로 벗어난 부분이 있다면 형식 문제를 고칠 때까지 풀 리퀘스트가 보류됩니다.

    참고

    코드 형식 변경만 담은 풀 리퀘스트는 보통 거부됩니다. 반면에 문서와 독스트링의 오타 및 문법 오류 수정은 환영합니다.

  3. 하위 호환성 문제를 염두에 두십시오. 무언가를 수용할 수 있는지에 대한 최종 결정은 결국 풀 리퀘스트를 처리하는 코어 개발자가 내리지만, 하위 호환성을 일찍부터 고려하면 이러한 이유로 풀 리퀘스트가 거부되는 일을 방지하는 데 도움이 됩니다. 풀 리퀘스트가 도입하는 변경 때문에 코드가 깨지게 될 사람의 입장이 되어 보십시오. 어떤 변경이든 누군가의 코드를 깨뜨릴 가능성이 꽤 높으며, 누군가에게 코드 수정을 강요하게 되므로 변경할 합당한 이유가 있어야 합니다. (물론 새 클래스나 함수에는 해당하지 않습니다. 새 인자는 선택적이어야 하며 기존 동작을 유지하는 기본값을 가져야 합니다.) 확신이 서지 않는다면 PEP 387을 살펴보거나 경험 많은 개발자들과 이 문제를 논의하십시오.

  4. 풀 리퀘스트가 예상대로 동작하는지 검증할 적절한 테스트를 반드시 갖추십시오. 적절한 테스트가 없는 풀 리퀘스트는 수락되지 않습니다!

  5. 모든 테스트가 통과하는지 확인하십시오. 변경 사항으로 인해 전체 테스트 스위트가 실패 없이 실행되어야 합니다. 변경의 영향을 받는 것으로 보이는 테스트만 실행하는 것으로는 충분하지 않습니다. 변경 사항과 인터프리터의 다른 부분 사이에 여러분이 모르는 간섭이 있을 수 있기 때문입니다.

  6. 풀 리퀘스트의 범위를 좁고 작게 유지하십시오. 풀 리퀘스트는 하나의 이슈를 다루거나 하나의 기능을 추가해야 합니다. 서로 관련 없는 여러 변경을 합치면 풀 리퀘스트를 리뷰하기 어려워지고 불필요하게 알림을 받는 사람의 수가 늘어납니다.

  7. 적절한 문서 추가/변경이 포함되어야 합니다.

NEWS 및 What’s New in Python 갱신하기

NEWS 항목이 필요한 변경 사항

코드베이스에 적용되는 변경 사항은 대부분 Misc/NEWS.d에 항목을 추가해야 하지만, 다음은 예외입니다:

  • 문서 변경 사항

  • 테스트 변경 사항

  • 사용자에게 드러나는 영향이 전혀 없는 순수한 내부 변경 사항

  • 이미 NEWS 항목이 있는 변경 사항

  • 아직 어떤 정식 릴리스(알파 및 베타 릴리스 포함)에도 포함되지 않은 되돌림

마지막 두 가지에 대해서는 다음 사항에 유의하십시오:

  1. 변경 사항이 릴리스 전에 되돌려진 경우, 해당 항목을 삭제하기만 하면 됩니다. 그렇지 않으면 변경 사항이 되돌려졌음을 알리는 새 항목을 추가해야 합니다(예를 들어, 어떤 기능이 알파에서 릴리스된 후 첫 번째 베타 전에 제외된 경우).

  2. 변경 사항이 아직 릴리스되지 않은 이전 변경 사항에 대한 수정(또는 기타 조정)이고 원래의 NEWS 항목이 여전히 유효하다면, 추가 항목은 필요하지 않습니다.

“What’s New in Python” 항목이 필요한 변경 사항

변경 사항이 최종 사용자에게 특히 흥미로운 경우(예를 들어, 새로운 기능, 상당한 개선 사항 또는 하위 호환성이 없는 변경 사항), NEWS 항목과 함께 “What’s New in Python” 문서(Doc/whatsnew/ 안의 3.X.rst 파일로, X는 현재 파이썬 버전입니다)에도 항목을 추가하십시오.

대부분의 경우 “What’s New in Python” 항목에는 NEWS 항목의 문구를 재사용하는 것으로 충분합니다.

참고

“What’s New in Python”에 항목이 필요한 변경 사항은 유지보수 릴리스에 포함하기에 적합하지 않을 가능성이 매우 높습니다.

NEWS 항목을 추가하는 방법

NEWS 항목은 Misc/NEWS.d 디렉터리에 개별 파일로 들어갑니다. NEWS 항목은 blurb-it을 사용하거나, blurb 도구와 그 blurb add 명령을 사용하여 만들 수 있습니다.

팁

blurb에 대한 자세한 내용은 해당 저장소에서 확인할 수 있습니다.

도구를 사용할 수 없다면 NEWS 항목 파일을 직접 만들 수 있습니다. Misc/NEWS.d 디렉터리에는 next라는 하위 디렉터리가 있으며, 여기에는 영향을 받은 대상의 분류를 나타내는 여러 하위 디렉터리가 들어 있습니다(예를 들어, 표준 라이브러리와 관련된 변경 사항은 Misc/NEWS.d/next/Library). 파일 이름 자체는 <datetime>.gh-issue-<issue-number>.<nonce>.rst 형식이어야 합니다:

  • <datetime>은 오늘 날짜와 현재 현지 시각을 하이픈(-)으로 이은 것으로, YYYY-MM-DD-hh-mm-ss 형식입니다(예: 2017-05-27-16-46-23).

  • <issue-number>는 변경 사항과 관련된 이슈 번호입니다(예: gh-issue-12345의 경우 12345).

  • <nonce>는 파일 이름이 여러 브랜치에 걸쳐 고유하도록 보장하는 고유한 문자열입니다(예: Yl4gI2). 일반적으로 여섯 글자이지만, 문자와 숫자로 이루어진 어떤 길이든 될 수 있습니다. 키보드로 임의의 문자를 입력하면 고유성을 충족할 수 있습니다.

결과적으로 파일 이름은 Misc/NEWS.d/next/Library/2017-05-27-16-46-23.gh-issue-12345.Yl4gI2.rst와 같은 형태가 될 수 있습니다.

NEWS 항목을 작성하는 방법

모든 NEWS 항목은 결국 변경 로그의 일부가 됩니다. 변경 로그에는 항목이 매우 많으며, 주된 독자는 코어 개발자나 기여자가 아니라 사용자입니다. NEWS 항목의 문구를 작성할 때 이 점을 고려하십시오. 변경 사항이 사용자에게 미치는 영향을 간결하고 정확하게 설명하십시오. 장황한 기술적 설명이나 여담은 피하고, 독자가 해당 변경의 실제 diff를 읽었을 것이라고 기대하거나 읽기를 요구하지 마십시오.

NEWS 파일의 내용은 유효한 reStructuredText여야 합니다. 열 너비는 80자로 맞춰야 합니다. 파일에는 들여쓰기나 앞머리 표시(예: -)가 없습니다. 이슈 번호는 파일 이름에 들어 있으므로 항목을 이슈 번호로 시작할 필요도 없습니다. 인라인 마크업도 사용할 수 있습니다. 다음은 NEWS 항목의 예입니다:

Fix warning message when :func:`os.chdir` fails inside
:func:`test.support.temp_cwd`. Contributed by Chris Jerdonek.

:func: 같은 인라인 Sphinx 역할을 사용하면 독자가 더 많은 정보를 찾는 데 도움이 됩니다. make html을 사용하여 HTML을 빌드하고 링크 대상이 적절한지 확인할 수 있습니다.

저작권

국제 조약으로 저작권을 보호받기 위해 저작권 표시를 해야 한다는 요건이 폐지되었으므로, 저작권 표시는 선택 사항이며 정보 제공용입니다. 하지만 저작권 표시는 여전히 정보를 알리는 역할을 합니다.

미국 저작권청에 따르면 유효한 저작권 표시에는 저작물이 처음 발행된 연도가 포함됩니다. 예를 들면 다음과 같습니다:

저작권 (C) 2001 Python Software Foundation.

이후 연도를 추가하려고 저작권 표시를 갱신할 필요는 없으며, 그러한 PR은 닫힙니다.

python/cpython#126133도 참고하십시오.

오타 수정

문서의 오타와 문법 오류를 수정하는 것은 연결된 이슈가 필요하지 않은 기여입니다. 이러한 수정에 가장 적합한 위치는 Doc/(최종 사용자 문서)와 InternalDocs/ 디렉터리입니다.

오타 수정 PR은 작고 초점이 분명하게 유지하십시오. 서로 관련 없는 많은 파일을 건드리는 큰 PR은 불필요하게 많은 리뷰어에게 알림을 보내며 리뷰하기도 더 어렵습니다. 큰 오타 수정 PR이나 위에 나열한 디렉터리 밖의 파일을 건드리는 PR은 이 절을 안내하며 닫힐 수 있습니다.

patchcheck

patchcheck는 진행 중인 변경 사항에 대한 간단한 자동 점검 목록으로, 개발자가 일반적인 점검 항목을 차례로 확인하도록 안내합니다. patchcheck를 실행하려면 다음과 같이 하십시오:

Unix에서(macOS 포함):

make patchcheck

Windows에서(빌드에 한 번이라도 성공한 뒤):

.\python.bat Tools\patchcheck\patchcheck.py

자동 점검 목록은 다음 항목을 확인합니다:

  • 문서를 갱신했습니까?

  • 테스트 스위트를 갱신했습니까?

  • Misc/NEWS.d/next 아래에 항목을 추가했습니까? (blurb-it 또는 blurb 도구 사용)

  • 필요한 경우 configure를 다시 생성했습니까?

  • 필요한 경우 pyconfig.h.in을 다시 생성했습니까?

이 목록은 완성된 풀 리퀘스트를 제출하기 전에 확인해야 할 사항을 기억하는 데 도움이 됩니다.

좋은 커밋 만들기

각 기능이나 버그 수정은 하나의 풀 리퀘스트에서 다루어야 하며, 각 풀 리퀘스트에는 여러 개의 커밋이 있을 수 있습니다. 특히 다음 사항을 지키십시오:

  • 하나의 커밋에서 둘 이상의 이슈를 수정하지 마십시오 (물론 하나의 코드 변경으로 모든 이슈가 수정되는 경우는 예외입니다).

  • 기능이나 버그 수정과 같은 커밋에서 관련 없는 코드를 외관상 변경하지 마십시오.

커밋 메시지는 다음 구조를 따라야 합니다:

Make the spam module more spammy

The spam module sporadically came up short on spam. This change
raises the amount of spam in the module by making it more spammy.

첫 줄 또는 첫 문장은 커밋의 목적이 무엇인지를 간결하고 핵심적으로 설명해야 합니다. ‘spam 모듈이 이제 더 spammy해졌습니다’와 같은 서술형보다는 (위 예제에서 사용한) 명령형을 강력히 권장합니다. 기존 제목 줄을 보려면 git log --oneline을 사용하십시오. 또한 첫 줄은 마침표로 끝나서는 안 됩니다.

이것만으로 커밋을 충분히 설명할 수 없다면, 무슨 일이 있었는지 충분히 깊이 있게 설명하는 새 문단을 하나 이상 추가할 수 있습니다 (커밋 메시지를 읽는 코어 팀 구성원이 변경의 근거를 이해할 수 있을 만큼 자세해야 합니다).

풀 리퀘스트를 병합할 때 커밋 메시지를 어떻게 작성해야 하는지에 대한 추가 지침은 Git 부트캠프를 확인하십시오.

참고

How to Write a Git Commit Message는 좋은 커밋 메시지를 작성하는 방법을 설명하는 훌륭한 글입니다.

라이선스

여러분의 변경을 받아들이려면 여러분의 작업을 PSF license에 따라 배포하는 것에 대한 여러분의 공식적인 승인이 있어야 합니다. 따라서 Python Software Foundation이 여러분의 코드를 Python에서 사용할 수 있도록 라이선스할 수 있게 허용하는 contributor agreement에 서명해야 합니다 (저작권은 여러분이 보유합니다).

참고

이 문서에는 한 번만 서명하면 되며, 이후 Python에 대한 여러분의 모든 기여에 적용됩니다.

CLA에 서명하는 데 필요한 단계는 다음과 같습니다:

  1. 변경을 만들어 풀 리퀘스트로 제출하십시오.

  2. python-cla-bot이 여러분의 풀 리퀘스트에 커밋 작성자가 기여자 라이선스 동의서(Contributor License Agreement)에 서명해야 한다는 댓글을 남기면, 댓글에 있는 버튼을 클릭하여 서명하십시오. GitHub로 로그인하고 “Authorize Python CLA Bot”을 클릭한 다음 “Sign”을 클릭하십시오.

  3. 서명하고 나면 python-cla-bot의 댓글이 “all commit authors signed the Contributor License Agreement”(모든 커밋 작성자가 기여자 라이선스 동의서에 서명했습니다)라고 표시하도록 갱신됩니다.

왜 CLA에 다시 서명해야 합니까?

원래 PR에 대해 이미 CLA에 서명했는데도 CLA 봇이 백포트 PR에 대해 CLA에 서명하라고 요청하는 경우가 있습니다. 이는 커밋에 사용하는 모든 이메일 주소에 대해 CLA에 서명해야 하기 때문입니다.

이런 상황은 Git 클라이언트에는 한 이메일 주소를 설정하고 그 주소로 CLA에 서명했지만, GitHub 계정에는 다른 기본 이메일(흔히 비공개 id+username@users.noreply.github.com 주소)을 설정한 경우에 발생할 수 있습니다.

  1. 원래 PR에서 CLA 봇은 커밋에 포함된 모든 이메일이 CLA에 서명했는지 확인합니다.

  2. 그런 다음 PR을 스쿼시 병합하는데, 이때 작성자의 기본 이메일을 사용하는 새 커밋이 하나 만들어집니다. 이 이메일은 원래 커밋할 때 사용한 이메일과 다를 수 있습니다.

  3. 백포트에는 이 새 커밋 하나만 있는 경우가 많습니다. 그러면 CLA 봇은 기본 이메일이 CLA에 서명했는지 확인합니다.

  4. 해결 방법은 백포트 PR에서 CLA not signed – click to sign 버튼을 클릭하는 것입니다.

팁

git config user.email을 실행하여 Git 클라이언트 설정을 확인하고, PR URL 끝에 .patch를 붙여 해당 PR의 커밋에 사용된 이메일을 확인하십시오:

제출하기

작업 결과가 만족스러우면 변경 사항을 브랜치에 커밋하십시오. 일반적으로 git commit -a를 실행하면 모든 것이 커밋됩니다. git status를 실행하면 언제든지 아직 커밋되지 않은 변경 사항을 확인할 수 있습니다.

모든 변경 사항이 커밋되면(즉, git status에 아무것도 표시되지 않으면) 브랜치를 포크에 푸시하십시오:

git push origin <branch name>

이렇게 하면 변경 사항이 GitHub에 올라갑니다.

이제 포크에서 풀 리퀘스트를 생성하십시오. issue tracker에 이미 있는 이슈에 대응하는 풀 리퀘스트라면, 풀 리퀘스트 제목에는 gh-NNNNN: 접두사를 사용하고 설명에는 #NNNNN을 사용하여 반드시 이슈 번호를 참조하십시오.

보고되지 않은 이슈에 대한 풀 리퀘스트라면(이슈 추적기에서 기존 이슈를 이미 검색해 보았다고 가정합니다) 새 이슈를 만들고 풀 리퀘스트에서 그 이슈를 참조하십시오. 정보가 부족해서 리뷰어가 풀 리퀘스트 리뷰를 미루는 일이 없도록 관련 세부 정보를 가능한 한 많이 기재하십시오.

이슈가 너무 간단해서 풀 리퀘스트가 해결하려는 문제에 대한 논의를 추적할 이슈가 필요 없다면(예를 들어 철자 오류 수정), 커밋 권한이 있는 사람이 풀 리퀘스트에 “skip issue” 레이블을 추가해야 합니다.

코드 리뷰 의견을 반영하다 보면 풀 리퀘스트에 여러 커밋이 포함될 수 있습니다. 스쿼시나 수정(amend) 등 GitHub에 강제 푸시가 필요한 작업을 하지 말고 풀 리퀘스트의 커밋 기록을 그대로 유지하십시오. 커밋 기록이 상세하면 리뷰어가 커밋 간의 diff를 볼 수 있으므로 자신의 의견이 반영되었는지 쉽게 확인할 수 있습니다. 커밋은 풀 리퀘스트가 병합될 때 스쿼시됩니다.

b.p.o의 기존 패치를 GitHub로 옮기기

issue tracker에 GitHub 풀 리퀘스트로 옮겨야 하는 패치가 있다면, 먼저 원래 패치 작성자에게 직접 풀 리퀘스트를 준비해 달라고 요청하십시오. 일주일이 지나도 작성자가 응답하지 않으면 다른 기여자가 기존 패치를 바탕으로 풀 리퀘스트를 준비해도 됩니다. 이 경우 양쪽 모두 CLA에 서명해야 합니다. 다른 사람의 패치를 바탕으로 풀 리퀘스트를 만들 때는 풀 리퀘스트 설명과 커밋 메시지에 “Co-authored-by: Author Name <email_address> .”를 추가하여 원래 패치 작성자를 명시하십시오. 공동 작성자 정보를 올바르게 추가하는 방법은 GitHub 문서를 참조하십시오.

Git에 패치 적용하기도 참조하십시오.

리뷰하기

우선, 인내심을 가져 주십시오! 풀 리퀘스트를 제출하는 사람이 여러분의 풀 리퀘스트를 리뷰할 수 있는 사람보다 훨씬 많습니다. 풀 리퀘스트를 리뷰받으려면 리뷰어에게 여러분의 풀 리퀘스트를 살펴볼 여유 시간과 동기가 있어야 합니다(누구에게도 풀 리퀘스트 리뷰를 강요할 수 없으며, 풀 리퀘스트를 살펴보는 일로 고용된 사람도 없습니다). 한 달이 지나도록 풀 리퀘스트가 리뷰어로부터 아무런 관심을 받지 못했다면(즉, 코멘트가 하나도 달리지 않았다면), 먼저 issue tracker에서 해당 이슈를 “핑”하여 구독자들에게 풀 리퀘스트에 리뷰가 필요하다는 사실을 상기시키십시오. 이슈를 핑한 후 일주일 안에 응답을 받지 못하면 Core Development Discourse category에 글을 올려 풀 리퀘스트를 리뷰해 줄 사람을 요청할 수 있습니다.

누군가가 시간을 내어 여러분의 풀 리퀘스트를 살펴보게 되면, 대개 어떻게 개선할 수 있는지에 관한 코멘트를 남길 것입니다(걱정하지 마십시오. Python의 코어 팀 구성원조차도 수정 요청과 함께 풀 리퀘스트를 돌려받곤 합니다). 그러면 여러분은 이러한 코멘트를 반영하도록 풀 리퀘스트를 갱신해야 하며, 이렇게 만족스러운 해결책이 나올 때까지 리뷰 과정이 반복됩니다.

풀 리퀘스트를 리뷰하는 방법

Python 개발 과정의 병목 중 하나는 코드 리뷰가 부족하다는 점입니다. 버그 추적기를 둘러보면, 많은 이슈에 수정 사항이 마련되어 있지만 제안된 해결책을 아무도 리뷰하지 않아 메인 소스 코드 저장소에 병합되지 못하고 있다는 것을 알 수 있습니다. 풀 리퀘스트를 리뷰하는 일은 풀 리퀘스트를 제출하는 것만큼이나 배울 점이 많으며, 다른 개발자의 작업에 건설적인 코멘트를 줄 수 있게 해 줍니다. 이 가이드는 코드 리뷰를 제출하기 위한 체크리스트를 제공합니다. 코드 리뷰가 유용하려면 완벽해야 한다는 것은 흔한 오해입니다. 전혀 그렇지 않습니다! 그저 풀 리퀘스트를 테스트하거나 코드를 이것저것 실행해 보고, 풀 리퀘스트나 이슈 추적기에 코멘트를 남기는 것만으로도 도움이 됩니다.

  1. 아직 하지 않았다면 설정 가이드를 따라 CPython 저장소의 사본을 받고, 빌드한 다음 테스트를 실행하십시오.

  2. 버그 추적기에서 이슈를 재현하는 데 필요한 단계를 확인하고, 저장소 안에서 ./python을 실행하여 띄울 수 있는 여러분 버전의 Python REPL(대화형 셸 프롬프트)에서 이슈를 재현할 수 있는지 확인하십시오.

  3. 풀 리퀘스트를 체크아웃하여 적용하십시오(다른 사람의 풀 리퀘스트 체크아웃하기 설명을 참조하십시오)

  4. 변경 사항이 C 파일에 영향을 준다면 빌드를 다시 실행하십시오.

  5. Python REPL(대화형 셸 프롬프트)을 실행하고 이슈를 재현할 수 있는지 확인하십시오. 이제 풀 리퀘스트가 적용되었으므로 이슈가 수정되어 있어야 합니다(이론상으로는 그렇지만, 실수는 일어나기 마련입니다! 좋은 리뷰는 코드가 Python 저장소에 병합되기 전에 이러한 실수를 잡아내는 것을 목표로 합니다). 또한 이 이슈나 관련 이슈에서 수정 사항의 작성자가 놓쳤을 수 있는 코너 케이스가 있는지도 살펴보십시오.

  6. 시간이 있다면 전체 테스트 스위트를 실행하십시오. 시간이 부족하다면 변경 사항이 적용된 모듈의 테스트를 실행하십시오. 그러나 풀 리퀘스트를 ‘병합 준비 완료’로 추천한다면, 항상 전체 테스트 스위트가 통과하는지 확인해야 한다는 점에 유의하십시오.

GitHub에서 풀 리퀘스트 리뷰 남기기

풀 리퀘스트를 리뷰할 때는 리뷰 과정에 관한 추가 세부 사항과 맥락을 제공해야 합니다.

단순히 풀 리퀘스트를 “승인”하는 대신 코멘트를 남기십시오. 예를 들면 다음과 같습니다:

  1. PR을 테스트했다면 결과와 함께 ‘Windows 10’, ‘Ubuntu 16.4’, ‘Mac High Sierra’처럼 테스트한 시스템과 버전을 알리십시오.

  2. 변경을 요청할 때는 어떻게 바꾸면 좋을지도 제안해 보십시오.

  3. 풀 리퀘스트의 “나쁜” 점만이 아니라 “좋은” 점에 대해서도 코멘트하십시오. 그렇게 하면 PR 작성자가 여러분의 코멘트에서 좋은 점을 더 쉽게 찾을 수 있습니다.

  4. 현재 PR에서 발생한 CI 실패를 살펴보십시오. PR 진행을 돕기 위해 할 수 있는 간단한 일은 아래의 “CI를 녹색으로 유지하기”를 참조하십시오.

다른 코어 팀 구성원의 리뷰 무효화하기

코어 팀 구성원은 요청된 변경 사항이 반영되었음을 확인했다면 다른 팀 구성원의 리뷰를 무효화할 수 있습니다. 코어 팀 구성원이 PR을 자신에게 할당했다면 그 PR을 적극적으로 살펴보고 있다는 표시이므로 그 구성원의 리뷰를 무효화해서는 안 됩니다.

지속적 통합을 녹색으로 유지하기

저희의 변경 관리 워크플로는 일반적으로 실패가 있는 PR의 병합을 허용하지 않습니다. 따라서 PR에서 CI 실패를 발견하면 무엇 때문인지 살펴보십시오.

보통 실패는 현재 PR의 변경 사항과 직접 관련되어 있습니다. 실패에 대해 짐작 가는 바가 있다면 리뷰 코멘트로 작성자에게 알려 주십시오. CI 실행은 때때로 수천 줄의 출력을 생성합니다. 트레이스백을 찾아 코멘트에 붙여 넣는 것처럼 간단한 일도 PR 작성자에게는 도움이 됩니다.

실패가 살펴보고 있는 변경 사항과 관련이 없어 보인다면, Release Status 빌드봇 대시보드에도 같은 실패가 나타나 있는지 확인하십시오. 그렇다면 그 실패는 이전 변경에서 발생한 것입니다. 빌드봇의 UI를 사용하여 어떤 PR이 문제를 일으켰는지 찾아낸 후, 그 문제가 다른 PR에도 영향을 준다고 코멘트할 수 있습니다.

그래도 실패 원인을 찾을 수 없다면, 실행된 검사 목록 옆에 “This branch is out-of-date with the base branch”(이 브랜치는 베이스 브랜치보다 오래되었습니다) 표시가 있는지 확인하십시오. 이 메시지 옆의 Update branch를 클릭하면 베이스 브랜치의 최신 변경 사항이 PR에 병합됩니다.

그래도 PR의 실패가 해결되지 않는다면, 실패한 해당 검사를 다시 실행해 볼 수 있습니다. Re-run jobs 버튼은 코어 팀과 트리아지 팀 구성원에게만 보인다는 점에 유의하십시오. 해당 권한이 있다면, 실패한 GitHub Action 작업으로 이동하여 오른쪽 위의 Re-run jobs를 클릭한 다음 Re-run failed jobs를 선택하십시오. 이 버튼은 다른 모든 작업이 끝난 후에만 나타납니다.

버튼에 접근할 수 없다면 해당 팀의 구성원에게 작업을 다시 실행해 달라고 요청하십시오. 또는 빈 커밋을 푸시하거나 Update branch 버튼으로 브랜치를 업데이트하여 직접 CI를 다시 실행시킬 수도 있습니다.

실패한 작업을 다시 실행하는 것을 가장 먼저 시도해서는 안 되지만, 분산 시스템에서는 간헐적인 실패가 발생할 수 있고 일부 단위 테스트는 과부하된 가상 머신에 민감하기 때문에 때로는 도움이 됩니다. 이런 불안정한 동작을 발견하면, issue tracker에서 이 특정 불안정성을 설명하는 이슈를 찾아보십시오. 찾을 수 없다면 새 이슈를 만드십시오.

Update branch 버튼

Update branch 버튼을 클릭하면 베이스 브랜치(보통 main)의 최신 변경 사항을 PR에 병합할 수 있습니다. 이는 오래된 PR의 CI를 녹색으로 유지하거나, CI 실패가 베이스 브랜치에서 수정되었는지 확인할 때 유용합니다.

PR이 아주 오래되었다면 병합하기 전에 브랜치를 업데이트하는 것이 좋을 수 있습니다. 그러면 CI가 마지막으로 실행된 이후 추가되거나 변경된 CI 검사에서 PR이 실패하지 않는지 확인할 수 있습니다.

정당한 이유 없이 Update branch를 클릭하지 마십시오. 실제로는 새 변경 사항이 없는데도 PR을 지켜보는 모든 사람에게 새 변경 사항이 있다는 알림이 가고, 한정된 CI 자원도 소모하기 때문입니다.

커밋/거절

풀 리퀘스트가 수용 가능한 상태에 도달하면(즉, “수락된” 것으로 간주되면) 병합되거나 거절됩니다. 거절되더라도 개인적으로 받아들이지 마십시오! 풀 리퀘스트의 병합 여부와 관계없이 여러분의 작업에 감사드립니다. Python에 무엇이 들어가고 무엇이 들어가지 않을지 균형을 잡는 일은 까다로우며, 모든 분의 기여를 다 받아들일 수는 없습니다.

하지만 풀 리퀘스트가 병합되면 Python의 VCS(버전 관리 시스템)에 들어가 Python의 다음 기능 릴리스와 함께 배포됩니다. 병합을 수행하는 코어 팀 구성원이 필요하다고 판단하면 버그 수정으로서 이전 버전의 Python에 백포트될 수도 있습니다.

공로 표시

사소하지 않은 기여는 What’s New in Python과 해당 기여의 NEWS 항목에 기여자로 기재되는 경우가 많습니다.