检查你的版本!

事物变化很快,贡献者指南也是如此。为确保你拥有最新版本的指南,请查看最新版本

参与 / 贡献#

Ray 不仅仅是一个分布式应用程序框架,它还是一个活跃的开发者、研究人员和机器学习爱好者的社区。

提示

我们的论坛上提问!社区非常活跃,乐于帮助大家成功构建 Ray 应用程序。

你可以在GitHub上加入(并 Star!)我们。

贡献 Ray#

我们欢迎(并鼓励!)对 Ray 的各种形式的贡献,包括但不限于:

  • 代码审查补丁和 PR。

  • 提交补丁。

  • 文档和示例。

  • 在论坛和 issue 中的社区参与。

  • 提高代码可读性和代码注释。

  • 测试用例以增强代码库的健壮性。

  • 推广项目的教程、博客文章、演讲。

  • 通过 Ray 增强提案 (REP) 进行功能和重大变更:ray-project/enhancements

我能做什么?#

我们使用 GitHub 来跟踪 issue、功能请求和 bug。查看标记为“good first issue”的条目,它们是开始的好地方。

设置你的开发环境#

要编辑 Ray 的源代码,请 fork 仓库,克隆它,然后从源代码构建 Ray。请遵循这些构建本地 Ray 副本的说明,以便轻松进行更改。

提交和合并贡献#

合并贡献有几个步骤。

  1. 首先将 master 的最新版本合并到你的开发分支。

    git remote add upstream https://github.com/ray-project/ray.git
    git pull . upstream/master
    
  2. 确保所有现有的测试代码风格检查都通过。运行 setup_hooks.sh 来创建一个 git hook,它会在你推送更改之前运行代码风格检查。

  3. 如果引入了新功能或修复了 bug,请务必在 ray/python/ray/tests/ 中的相关文件中添加新的测试用例。

  4. 记录代码。公共函数需要记录,并且如果适用,请记得提供使用示例。有关编辑和构建公共文档的说明,请参阅 doc/README.md

  5. 处理 PR 上的评论。在审查过程中,你可能需要处理与其他更改的合并冲突。要解决合并冲突,请在你的分支上运行 git pull . upstream/master(请勿使用 rebase,因为它对 GitHub 审查工具不太友好。所有提交将在合并时被压缩。)

  6. 审查者将合并并批准 PR;如果 PR 过期,请务必提醒他们。

PR 审查流程#

对于在 ray-project 组织中的贡献者:#

  • 创建 PR 时,请在 assignee 部分添加一个审查者。

  • 被分配者将审查你的 PR,并在需要进一步操作时添加 @author-action-required 标签。

  • 处理他们的评论,并从 PR 中删除 @author-action-required 标签。

  • 重复此过程,直到被分配者批准你的 PR。

  • PR 被批准后,作者负责确保 PR 通过构建。如果构建成功,请添加 test-ok 标签。

  • 提交者将在构建通过后合并 PR。

对于不在 ray-project 组织中的贡献者:#

  • 你的 PR 将很快被分配审查者。PR 的被分配者将积极与贡献者沟通以合并 PR。

  • 处理完评论后,请积极提醒被分配者!

测试#

尽管我们有钩子可以在每次拉取请求时自动运行单元测试,但我们建议你提前在本地运行单元测试,以减轻审查者的负担并加快审查过程。

如果你是第一次运行测试,可以使用以下命令安装所需的依赖项:

pip install -c python/requirements_compiled.txt -r python/requirements/test-requirements.txt

Python 开发测试#

完整的测试套件对于单台机器来说太大了。但是,你可以运行单个相关的 Python 测试文件。假设某个文件中的一个测试,例如 python/ray/tests/test_basic.py,正在失败。你可以像这样在本地仅运行该测试文件:

# Directly calling `pytest -v ...` may lose import paths.
python -m pytest -v -s python/ray/tests/test_basic.py

这将运行该文件中的所有测试。要运行特定测试,请使用以下命令:

# Directly calling `pytest -v ...` may lose import paths.
python -m pytest -v -s test_file.py::name_of_the_test

C++ 开发测试#

要编译并运行所有 C++ 测试,你可以运行:

bazel test $(bazel query 'kind(cc_test, ...)')

或者,你也可以运行一个特定的 C++ 测试。你可以使用:

bazel test $(bazel query 'kind(cc_test, ...)') --test_filter=ClientConnectionTest --test_output=streamed

代码风格#

一般来说,对于 C++ 代码,我们遵循Google 风格指南;对于 Python 代码,我们遵循Black 代码风格。Python 导入遵循PEP8 风格。但是,代码在局部保持一致的风格比严格遵循指南更重要。如有疑问,请遵循组件的本地代码风格。

对于 Python 文档,我们遵循Google pydoc 格式的一个子集。以下代码片段展示了标准的 Ray pydoc 格式:

def ray_canonical_doc_style(param1: int, param2: str) -> bool:
    """First sentence MUST be inline with the quotes and fit on one line.

    Additional explanatory text can be added in paragraphs such as this one.
    Do not introduce multi-line first sentences.

    Examples:
        .. doctest::

            >>> # Provide code examples for key use cases, as possible.
            >>> ray_canonical_doc_style(41, "hello")
            True

            >>> # A second example.
            >>> ray_canonical_doc_style(72, "goodbye")
            False

    Args:
        param1: The first parameter. Do not include the types in the
            docstring. They should be defined only in the signature.
            Multi-line parameter docs should be indented by four spaces.
        param2: The second parameter.

    Returns:
        The return value. Do not include types here.
    """
class RayClass:
    """The summary line for a class docstring should fit on one line.

    Additional explanatory text can be added in paragraphs such as this one.
    Do not introduce multi-line first sentences.

    The __init__ method is documented here in the class level docstring.

    All the public methods and attributes should have docstrings.

    Examples:
        .. testcode::

            obj = RayClass(12, "world")
            obj.increment_attr1()

    Args:
        param1: The first parameter. Do not include the types in the
            docstring. They should be defined only in the signature.
            Multi-line parameter docs should be indented by four spaces.
        param2: The second parameter.
    """

    def __init__(self, param1: int, param2: str):
        #: Public attribute is documented here.
        self.attr1 = param1
        #: Public attribute is documented here.
        self.attr2 = param2

    @property
    def attr3(self) -> str:
        """Public property of the class.

        Properties created with the @property decorator
        should be documented here.
        """
        return "hello"

    def increment_attr1(self) -> None:
        """Class methods are similar to regular functions.

        See above about how to document functions.
        """

        self.attr1 = self.attr1 + 1

有关如何在 docstrings 中编写代码片段的更多详细信息,请参阅此处

代码格式化和 linting#

我们还有代码格式化和 linting 的测试,这些测试需要在合并前通过。

pip install -c python/requirements_compiled.txt -r python/requirements/lint-requirements.txt
  • 如果为 C++ 开发,你将需要clang-format版本 12(请从这里下载此版本的 Clang)。

你可以在本地运行以下命令:

pip install -U pre-commit==3.5.0
pre-commit install  # automatic checks before committing
pre-commit run ruff -a

如下输出表明失败:

WARNING: clang-format is not installed!  # This is harmless
From https://github.com/ray-project/ray
 * branch                master     -> FETCH_HEAD
python/ray/util/sgd/tf/tf_runner.py:4:1: F401 'numpy as np' imported but unused  # Below is the failure

此外,还有其他组件的格式化和语义检查器,例如(不包含在 pre-commit 中):

  • Python README 格式

cd python
python setup.py check --restructuredtext --strict --metadata
  • Python 和文档禁止词检查

./ci/lint/check-banned-words.sh
  • Bazel 格式

./ci/lint/bazel-format.sh
  • clang-tidy 用于 C++ lint,需要安装 clangclang-tidy 版本 12。

./ci/lint/check-git-clang-tidy-output.sh

理解 CI 测试任务#

Ray 项目在 PR 打开后,会自动使用 Buildkite 和多个 CI 测试任务运行持续集成 (CI) 测试。

CI 测试文件夹包含所有集成测试脚本,它们通过 pytest、基于 bazel 的测试或其他 bash 脚本调用其他测试脚本。一些示例如下:

  • Bazel 测试命令
    • bazel test --build_tests_only //:all

  • Ray Serving 测试命令
    • pytest python/ray/serve/tests

    • python python/ray/serve/examples/echo_full.py

如果 CI 构建异常似乎与你的更改无关,请访问此链接查看最近已知的flaky 测试。

API 兼容性风格指南#

Ray 为 Ray core 和库中的公共 API 提供稳定性保证,这在API 稳定性指南中有描述。

很难将 API 兼容性的语义完全捕获到一个注释中(例如,公共 API 可能有“实验性”参数)。对于更细粒度的稳定性约定,可以在 pydoc 中注明(例如,“random_shuffle 选项是实验性的”)。尽可能,实验性参数也应该在 Python 中以其下划线为前缀(例如,_owner=)。

其他建议:

在 Python API 中,请考虑强制使用 kwargs 而不是位置参数(使用 * 操作符)。Kwargs 比位置参数更容易保持向后兼容,例如,想象一下如果你需要弃用下面的“opt1”,使用强制 kwargs 会更容易。

def foo_bar(file, *, opt1=x, opt2=y)
    pass

对于回调 API,请考虑添加一个 **kwargs 占位符作为“前向兼容占位符”,以便将来可能传递更多参数给回调,例如:

def tune_user_callback(model, score, **future_kwargs):
    pass

社区示例#

我们一直在寻找新的示例贡献!当为 Ray 库贡献示例时,请在该库的 examples.yml 文件中包含指向你示例的链接。

- title: Serve a Java App
  skill_level: advanced
  link: tutorials/java
  contributor: community

为你的示例指定一个标题、一个技能水平(beginnerintermediateadvanced)和一个链接(相对链接指向其他文档页面,但以 http:// 开头的直接链接也有效)。包含 contributor: community 元数据,以确保示例在示例库中被正确标记为社区示例。

成为审查者#

我们从活跃的贡献者中识别审查者。审查者不仅积极为项目做出贡献,还愿意参与新贡献的代码审查。项目的一个拉取请求必须至少由一名审查者审查才能合并。目前没有正式流程,但 Ray 的当前审查者将主动联系活跃的 Ray 贡献者。

更多参与方式#

Ray 不仅仅是一个分布式应用程序框架,它还是一个活跃的开发者、研究人员和机器学习爱好者的社区。以下是一些参与 Ray 社区的技巧:

  • 加入我们的社区 Slack来讨论 Ray!

  • GitHub上 Star 和关注我们。

  • 要发布问题或功能请求,请查看讨论板

  • Twitter上关注我们并传播信息。

  • 加入我们的Meetup Group,与社区中的其他人建立联系。

  • StackOverflow上使用 [ray] 标签来提问和回答关于 Ray 用法的问题。

注意

这些技巧基于 TVM 的贡献者指南