기여 지침

기여 지침 (Contribution Guidelines)

Apache Pinot에 기여할 때 따라야 할 지침을 다루는 문서예요. 기여를 시작하기 전에 개발 환경 설정과 코드 모듈과 구성 섹션을 검토하고, pinot 소스 코드의 자체 fork를 만들었는지 확인해요.

출처: 문서

본문

기여를 시작하기 전에 개발 환경 설정과 코드 모듈과 구성 섹션을 검토하고 pinot 소스 코드의 자체 fork를 만들었는지 확인하세요.

Pinot 개선 제안 워크플로우 (Pinot Enhancement Proposal Workflow)

Apache Pinot 커뮤니티는 멤버가 프로젝트의 전반적인 성장과 성공에 기여하도록 권장해요. 모든 기여자는 개선을 제안할 때(PEP - Pinot Enhancement Proposal라고도 함) 다음 지침을 따라야 해요.

모든 개선 사항은 범위/크기와 관계없이 Github issue로 시작해야 해요. 이슈는 다음 정보를 명확히 명시해야 해요:

  • 무엇이 되어야 하는가?
  • 기능이 왜 필요한가 (예: 사용 사례 설명).
  • 방법에 대한 초기 아이디어/제안을 포함할 수도 있어요.
  • Github issue는 PEP-Request 레이블로 태그되어야 해요.

Github issue가 제출되면:

  • PMC는 상세 제안/설계 문서가 필요한지, 아니면 간단히 PR로 이어져도 되는지 결정해요.
  • PMC가 구현으로 넘어가기 전에 이슈/제안을 검토할 충분한 시간(예: 5 영업일)이 주어져야 해요.
  • 구현을 진행하는 데 PMC의 +1 하나와 -1 0개 투표를 사용할 수 있어요.
  • 구현 중에 기능이 처음 예상한 것보다 훨씬 복잡하다는 것이 발견되면 PMC는 상세 설계 문서를 요청할 수 있어요.

PMC는 PEP가 명시적 제안/설계 문서를 요구하는지, 아니면 Github issue 링크를 포함한 PR로만 진행돼도 되는지 결정할 때 다음 지침을 사용해요.

  • 새 주요 기능, 하위 시스템, 또는 기능 조각.
  • 잠재적으로 하위 호환성 위반을 만들 수 있는 변경:
    • 프로젝트의 공용 인터페이스에 영향을 주는 변경.
    • SPI 변경
    • 새 API 리소스 추가, 또는 broker-server-controller 통신 변경.
  • 성능에 영향을 줄 수 있는 변경.

요청이 PMC의 직접 PR 단계로 가는 것에 +1 하나 이상, -1 0개를 받으면 요청자는 Github issue 링크와 함께 PR을 제출할 수 있어요.

요청이 제안을 요구하면, 요청자는 PR을 제출하기 전에 제안 설계 문서를 제공해야 해요. 설계 문서는 공개 읽기·댓글 접근을 가져야 해요. (조직이 공개 접근을 허용하지 않으면 자유롭게 이용 가능한 다른 플랫폼에 문서를 호스팅하세요). 설계 문서는 다음을 포함해야 해요:

  • 동기 (Motivation): 왜 그러한 사용 사례가 있는지 등 세부 사항을 포함해 해결할 문제를 설명해요.
  • 제안된 변경 (Proposed Change): 새로 해야 할 일을 설명해요. 변경 범위에 따라 상당히 방대하고 큰 하위 섹션이 있을 수도, 몇 문장일 수도 있어요. 또한 "어떻게"를 세부 사항·가능한 POC와 함께 설명해요.
  • 새롭거나 변경된 공용 인터페이스 (New or Changed Public Interfaces): 위에서 설명한 "호환성 약속" 중 하나에 대한 영향. 이것은 모두가 생각하도록 특히 강조하고 싶어요.
  • 배포, 마이그레이션 계획과 호환성 (Deployment, Migration Plan and Compatibility): 이 기능이 무중단 업그레이드를 위한 추가 지원을 요구한다면 어떻게 작동할지 설명해요.
  • 거부된 대안 (Rejected Alternatives): 고려한 다른 대안은 무엇이며 왜 더 나쁜가? 이 섹션의 목표는 사람들이 왜 이것이 지금 최선의 해결책인지 이해하게 하고, 예전 대안이 재고될 때 미래의 변동을 방지하는 것이에요.
  • PMC 검토 상태 (PMC Review Status): 제안/설계 문서는 문서 시작 부분에 리뷰어 이름과 검토 상태를 포함한 검토 상태 표를 포함할 수 있어요.

제안/설계 문서는 기본적으로 모든 커뮤니티 멤버에게 댓글 접근이 활성화된 google doc에 있어야 해요(권한 요청이 필요하지 않아야 함). 유일한 예외는 이슈의 초기 제안이 일반적으로 수용되는 작은 기능이에요. 제안/설계 문서가 승인되면(모든 질문/댓글 해결) 모든 Pinot 제안/설계 문서를 제출해야 하는 공용 Google Drive로 이전해야 해요.

  • 일부 멤버와의 오프라인 회의/논의가 있으면 회의 노트를 캡처해 문서에 추가해야 해요.
  • 일반 지침
    • 리뷰하기 쉬운 더 작은 PR
    • 순수 리팩터링 PR은 기능을 변경하는 PR과 분리해야 해요. 리팩터링 PR은 리뷰어를 위한 도움으로 그렇게 명시할 수 있어요. 예를 들어 패키지 이동은 PR에 거대한 diff로 나타날 수 있어요.

설계 문서 만들기 (Create a design document)

변경이 비교적 사소하면 이 단계를 건너뛸 수 있어요. 새 주요 기능을 추가한다면 설계 문서를 추가하고 코드를 제출하기 전에 커뮤니티의 의견을 구할 것을 권장해요.

여기에 현재 설계 문서 목록이 있어요.

변경을 위한 이슈 만들기 (Create an issue for the change)

변경하려는 내용에 대해 여기에서 Pinot issue를 만들어요. 변경이 필요한 이유와 해결 방법에 대한 정보를 제공해요. 이슈의 대화를 사용해 가정과 올바른 진행 방법을 검증해요. 하위·상위 호환성 변경과 외부 라이브러리와 의존성 관리 섹션을 반드시 검토하세요.

설계 문서가 있으면 이슈에서 설계 문서를 참조해요. 변경 범위에 따라 여러 이슈를 만들 수도 있어요.

무엇을 할지 분명해지면 아래 나열된 다음 단계로 진행해요.

변경을 위한 브랜치 만들기 (Create a branch for your change)

$ cd pinot
#
# ensure you are starting from the latest code base
# the following steps, ensure your fork's (origin's) master is up-to-date
#
$ git fetch upstream
$ git checkout master
$ git merge upstream/master
# create a branch for your issue
$ git checkout -b <your issue branch>

필요한 변경을 만드세요. 계획한 변경이 너무 크면 더 작은 작업으로 나누세요.

변경하기 (Making the changes)

변경할 때 여기에 적힌 권장 사항/모범 사례를 따르세요.

코드 문서화 (Code documentation)

코드가 적절히 문서화되도록 하세요. 문서화에 고려할 몇 가지:

  • 항상 클래스 수준 java doc을 포함. 최상위 클래스 수준에서 우리는 클래스가 제공하는 기능, 클래스가 유지하는 상태, 동시성/스레드 안전성 우려, 클래스가 보일 수 있는 예외 동작에 대한 정보를 찾아요.
  • 공용 메서드와 파라미터를 문서화.

로깅 (Logging)

  • 정상 경로와 예외 경로 모두 적절한 로깅이 있는지 확인. 이에 대한 추론으로 로그가 시끄럽지 않도록 해요.
  • 메시지 로깅에 System.out.println을 사용하지 마세요. slf4j 로거를 사용하세요.
  • 로깅 수준을 올바르게 사용: 디버깅에만 유용한 자세한 로그는 수준을 debug로 설정.
  • 예외의 printStackTrace 메서드로 스택 트레이스를 기록하지 마세요.

예외와 예외 처리 (Exceptions and Exception-Handling)

  • 가능하면 구체적인 예외, 가능하면 확인된 예외(checked exceptions)를 던져 호출자가 처리해야 할 오류 조건을 쉽게 결정할 수 있게 해요.
  • 스레드/runnable의 run() 메서드인 경우를 제외하고 넓은 예외(즉 catch (Exception e) 블록)를 잡는 것을 피해요.

현재 Pinot 코드는 이를 엄격히 따르지 않지만, 시간이 지나면서 이를 변경하고 예외 처리에 대한 모범 사례를 채택하고 싶어요.

하위·상위 호환성 변경 (Backward and Forward compatibility changes)

Zookeeper 또는 세그먼트에 저장된 상태를 변경한다면 하위·상위 호환성 문제를 모두 고려했는지 확인하세요.

  • 하위 호환성의 경우, 한 컴포넌트가 새 버전을 사용하고 다른 컴포넌트가 여전히 예전 버전을 사용하는 경우를 고려하세요. 예: broker와 server 사이의 요청 형식이 업데이트되면, 새 broker가 예전 server와 대화할 때의 결과 동작을 고려해 보세요. 깨질까요?
  • 상위 호환성의 경우, 롤백 경우를 고려하세요. 예: 새 코드가 영속한 상태를 예전 코드가 처리할 때 어떻게 되는지. 예전 코드가 새 필드를 건너뛰나요?

외부 라이브러리와 의존성 관리 (External libraries and dependency management)

외부 의존성을 끌어들일 때 주의하세요. 새 라이브러리를 가져와야 할 필요에 직면했을 때 여러 가지를 고려해야 해요.

  • 라이브러리 추가가 제공하는 기능은 무엇인가? 기존 라이브러리가 이 기능을 제공할 수 있나(약간의 노력으로)?
  • 외부 라이브러리가 활발한 기여자 커뮤니티에 의해 유지되고 있나?
  • 라이브러리의 라이선스 조건은 무엇인가. 라이선스 처리에 대한 자세한 내용은 새로 추가된 파일의 라이선스 헤더를 참조.
  • 라이브러리를 기초 모듈 (Foundational modules)에 추가하는가? 이는 나머지 Pinot 코드베이스에 영향을 준다. 새 라이브러리가 많은 전이 의존성을 끌어오면 클래스패스에 여러 클래스가 있는 예상치 못한 문제가 발생할 수 있다. 이러한 문제는 런타임에 라이브러리를 로드하는 순서가 중요하므로 테스트로 잡기 어렵다. 지원이 절대적으로 필요하면 확장 모듈 (Extension modules)을 통해 추가하는 것을 고려해 봐.

새 의존성을 추가할 때는 의존성 관리 지침을 따라 모범 사례를 지키고 코드베이스 전반에 걸쳐 의존성이 일관되게 관리되도록 하세요.

변경 사항 테스트 (Testing your changes)

기여에는 자동화된 테스트가 항상 권장돼요. 다음과 같이 테스트를 작성하세요:

  1. 기여의 정확성을 검증. 이것은 자신과 리뷰어에게 증거가 돼요.
  2. 코드 리팩터나 다른 변경에 대한 기여의 미래 대비. 항상 가능하지는 않지만(테스트 지침 참조), 목표로 삼을 만한 좋은 목표예요.

변경에 대한 테스트 목록을 식별하세요. 변경 범위에 따라 다음 중 하나 이상이 필요할 수 있어요:

  • 단위 테스트

    코드에 필요한 클래스·메서드 수준 단위 테스트가 있는지 확인. 긍정 사례와 부정 사례 테스트를 모두 쓰는 것이 중요해요. 테스트를 잘 문서화하고 의미 있는 단언(assertion)을 추가하세요; 단언이 실패하면 다른 사람이 디버깅할 수 있는 정보와 함께 올바른 메시지가 기록되도록 하세요.

  • 통합 테스트

    mocking에 의존하지 않고 End-to-End 경로를 다루는 통합 테스트를 추가하세요(아래 참고 참조). REST API에 대한 통합 테스트를 반드시 추가하고, API의 명시적 계약인 서로 다른 오류 코드, 즉 200 OK, 4xx 또는 5xx 오류를 다루는 테스트를 포함해야 해요.

테스트 지침 (Testing Guidelines)

  • 테스트 코드에는 TestNG 사용

    TestNG로 테스트 클래스, 어노테이션, 단언을 작성하세요. Checkstyle은 테스트 소스에서 JUnit 테스트 API import(org.junit)를 거부해요; JUnit Platform 스위트 API는 TestNG 스위트 그룹화에 사용 가능하게 남아 있어요. 빌드가 유지하는 JUnit 의존성은 테스트 인프라를 지원하지 JUnit 테스트를 지원하지 않아요. PR #19675 참조.

  • Mocking

    Mockito를 사용해 특정 동작을 제어하도록 클래스를 mock — 예: 다양한 오류 조건 시뮬레이션.

참고

PowerMock 같은 고급 mock 라이브러리를 사용하지 마세요. 이들은 정적/비공개 멤버를 테스트하기 위해 바이트코드 수준 변경을 하지만, 이는 일반적으로 jacoco 같은 다른 도구를 실패하게 해요. 또한 추가 변경을 테스트하기 더 어렵게 만드는 잘못된 구현 선택을 조장해요. PowerMock이나 고급 mocking 옵션을 선택해야 할 때는 mock과 더 잘 작동하도록 코드를 리팩터해야 하거나, 실제로 단위 테스트 대신 통합 테스트를 작성해야 할 수도 있어요.

  • 테스트에서 가정 검증

    테스트가 올바른 이유로 통과하는지 검증하는 적절한 단언이 테스트에 추가되었는지 확인하세요.

  • 신뢰할 수 있는 테스트 작성

    신뢰할 수 있는 테스트를 작성하세요. 테스트가 비동기 이벤트가 발생하는 것에 의존한다면 테스트에 sleep을 추가하지 마세요. 가능하면 적절한 mocking이나 조건 기반 트리거를 사용하세요.

새로 추가된 파일의 라이선스 헤더 (License Headers for newly added files)

모든 소스 코드 파일에는 라이선스 헤더가 있어야 해요. 체크인할 새 파일에 헤더를 자동으로 추가하려면 pinot 최상위 폴더에서 실행:

mvn license:format

참고

서드파티 코드나 파일을 체크인한다면 Apache 지침을 검토하세요:

끌어들이는 코드가 위 지침을 준수한다고 판단되면 변경 사항을 끌어들이세요. 이들의 라이선스 헤더는 추가하지 마세요. Apache 라이선스 프로세스를 준수하도록 다음 지침을 따르세요:

  • pinot/licenses 아래에 포함된 라이브러리의 라이선스 조건이 있는 LICENSE-<newlib> 파일을 추가하세요.
  • pinot/LICENSE 파일을 업데이트해 해당 지원 라이선스 아래에 새로 추가된 라이브러리 파일 경로를 표시하세요.
  • 부모 pom pinot/pom.xml의 license와 rat maven 플러그인에 대한 제외 규칙을 업데이트하세요.

라이선스 조건에 대한 주의를 일찍 기울이지 않으면, 새 릴리스를 준비할 때 훨씬 나중에 잡힐 거예요. 그 시점에 올바른 라이브러리로 작업하도록 코드를 업데이트하는 것은 더 큰 리팩터링 변경을 요구하고 릴리스 과정을 지연시킬 수 있어요.

풀 리퀘스트(PR) 만들기 (Creating a Pull Request (PR))

  • 코드 스타일 검증 (Verifying code-style)

    PR을 게시하기 전에 코드 스타일을 검증하려면 다음 명령을 실행하세요:

mvn checkstyle:check
  • 테스트 실행 (Run tests)

    변경 사항에 대한 리뷰 요청을 만들기 전에 변경 사항에 해당하는 단위 테스트를 실행했는지 확인하세요. IDE 또는 maven 명령줄로 개별 테스트를 실행할 수 있어요. 마지막으로 mvn clean install -Pbin-dist를 실행해 모든 테스트를 로컬에서 실행하세요.

    성능 문제나 경쟁 조건과 관련된 변경의 경우 신뢰할 수 있는 테스트를 작성하기 어려우므로, 변경 사항을 검증하기 위해 수동 스트레스 테스트를 실행하는 것을 권장해요. PR 설명에 수행한 수동 테스트를 반드시 기록해야 해요.

  • 변경 사항 푸시 및 리뷰용 PR 생성

    의미 있는 커밋 메시지로 변경 사항을 커밋하세요.

$ git add <files required for the change>
$ git commit -m "Meaningful oneliner for the change"
$ git push origin <your issue branch>

After this, create a PullRequest in `github <https://github.com/apache/pinot/pulls>`_. Include the following information in the description:

  * The changes that are included in the PR.

  * Design document, if any.

  * Information on any implementation choices that were made.

  * Evidence of sufficient testing. You ``MUST`` indicate the tests done, either manually or automated.

PR이 생성되면 코드베이스가 컴파일되고 모든 테스트가 travis를 통해 실행돼요. travis가 표시하는 문제를 추적하고 해결하세요. 간헐적인 테스트 실패가 보이면 추적할 이슈를 만드세요.

travis 실행이 깨끗하면 프로젝트의 커미터를 최소 2명에게 리뷰를 요청하고, 이슈에 대해 리뷰어와 부드럽게 후속 조치하세요.

  • 변경 사항에 대한 github 댓글을 받으면 github에서 응답하고 우려 사항을 해결하세요. 논의 중인 변경에 대해 오프라인 논의가 있으면 다른 사람도 따라올 수 있도록 논의 결과를 캡처하세요.

    변경이 리뷰되는 동안 master 브랜치에 다른 변경이 이루어졌을 수 있어요. 변경 사항을 새 변경 사항에 리베이스하세요:

# commit your changes
$ git add <updated files>
$ git commit -m "Meaningful message for the udpate"
# pull new changes
$ git checkout master
$ git merge upstream/master
$ git checkout <your issue branch>
$ git rebase master

At this time, if rebase flags any conflicts, resolve the conflicts and follow the instructions provided by the rebase command.

Run additional tests/validations for the new changes and update the PR by pushing your changes:
$ git push origin <your issue branch>
  • 모든 댓글을 처리하고 승인된 PR이 있으면 커미터 중 한 명이 PR을 병합할 수 있어요.
  • 변경이 병합된 후 문서를 업데이트해야 하는지 확인하세요. 그렇다면 문서용 PR을 만드세요.

문서 업데이트 (Update Documentation)

일반적으로 새 기능, 기능, API 변경에 대해서는 사용자를 최신 상태로 유지하고 개발을 추적하기 위해 문서 업데이트가 필요해요.

이 링크에 따라 문서 업데이트를 하세요.

더 알아보기 (Learn more)