跳到主要内容

指南

拉取请求(Pull Request)指南

我们强烈鼓励遵循的原则是

在创建拉取请求(PR)之前,请先创建一个议题(issue)。

目的是将问题与可能的解决方案分开。

错误修复: 如果您只是修复一个小错误,可以直接提交拉取请求,但我们强烈建议您提交一个议题(issue),详细说明您要修复的内容。这有助于我们在不接受特定修复时仍能跟踪该问题。请记住,项目维护者保留接受或拒绝传入拉取请求的权利,因此最好将问题和修复代码分开。在某些情况下,项目维护者可能会要求您在继续之前从拉取请求中创建一个单独的议题。

重构: 对于小型重构,它可以是一个独立的拉取请求(PR),详细说明您正在重构什么以及为什么。如果存在疑虑,项目维护者可能会要求您在继续之前为该拉取请求创建一份 #SIP

功能/大型更改: 如果您打算更改公共 API,或对实现进行任何非琐碎的更改,我们要求您提交一个新的议题作为 #SIP (Superset 改进提案)。这使我们能够在您投入大量精力之前就您的提案达成一致。欢迎您随 SIP 一起提交拉取请求(有时为了演示是必要的),但在 SIP 获得批准之前,我们不会审查/合并代码。

一般来说,小型拉取请求(PR)总是比大型拉取请求更容易审查。最佳实践是将您的工作分解为更小、独立的拉取请求,并引用相同的议题。这将大大减少周转时间。

如果您希望分享尚未准备好合并的工作,请创建一个 草稿拉取请求(Draft PR)。这将使维护者和 CI 运行器能够优先处理成熟的拉取请求。

最后,永远不要提交会导致 master 分支处于损坏状态的拉取请求(PR)。如果该拉取请求是完成一个大型功能的多个拉取请求的一部分,并且无法独立运行,您可以创建一个功能分支,并将所有相关的拉取请求合并到该功能分支中,然后再从功能分支创建拉取请求到 master 分支。

协议

编写

  • 填写拉取请求(PR)模板的所有部分。

  • 为拉取请求(PR)标题添加以下语义前缀之一(受 Karma 启发)

    • feat (新功能)
    • fix (错误修复)
    • docs (文档更改)
    • style (格式化、缺少分号等;无应用逻辑更改)
    • refactor (代码重构)
    • test (添加缺失测试、重构测试;无应用逻辑更改)
    • chore (更新任务等;无应用逻辑更改)
    • perf (性能相关更改)
    • build (构建工具、Docker 配置更改)
    • ci (测试运行器、GitHub Actions 工作流更改)
    • other (不属于上述类别的更改——应很少见!)
    • 示例
      • feat: 将图表导出为 ZIP 文件
      • perf(api): 提升 API 信息性能
      • fix(chart-api): 缓存指示器总是显示值已缓存
  • 如果尚未准备好审查(WIP = work-in-progress,工作进行中),请在标题中添加前缀 [WIP]。我们建议首先创建一个带有 [WIP] 的拉取请求(PR),并在通过 CI 测试并至少通读一次您的代码更改后将其移除。

  • 如果您认为您的拉取请求(PR)可能引入破坏性更改,请在语义前缀之后但在冒号之前,在拉取请求标题中添加一个 !,例如:feat!: Added foo functionality to bar

  • 屏幕截图/GIF: 用户界面更改需要提供前后屏幕截图,或交互 GIF 图

    • 推荐的截屏工具 (Kap, LICEcap, Skitch)
    • 如果没有提供屏幕截图,提交者将用 need:screenshot 标签标记该拉取请求(PR),并且在提供屏幕截图之前不会进行审查。
  • 依赖: 请谨慎添加新依赖,并避免不必要的依赖。

    • 对于 Python,请将其包含在 pyproject.toml 中,注明任何特定限制,并将其在 requirements.txt 中固定到特定版本,以确保应用程序构建的可确定性。
    • 对于 TypeScript/JavaScript,请将新库包含在 package.json
  • 测试: 拉取请求应包含测试,可以是 doctests、单元测试或两者。请确保解决所有错误和测试失败。有关如何运行测试,请参阅测试

  • 文档: 如果拉取请求添加了功能,则文档应作为同一拉取请求的一部分进行更新。

  • CI: 审查者将不会审查代码,直到所有 CI 测试通过。有时可能会出现不稳定的测试。您可以关闭并重新打开拉取请求(PR)以重新运行 CI 测试。如果问题仍然存在,请报告。在 CI 修复程序部署到 master 后,请重新基于您的拉取请求。

  • 代码覆盖率: 请确保代码覆盖率不会降低。

  • 准备好审查后,请移除 [WIP]。请注意,拉取请求(PR)可能在批准后很快合并,因此请确保拉取请求已准备好合并,并且不要期望有更多时间进行批准后的编辑。

  • 如果拉取请求(PR)未准备好审查且不活跃超过 30 天,我们将因不活跃而关闭它。作者欢迎重新打开并更新。

审查

  • 撰写审查意见时请使用建设性语气。
  • 如果需要更改,请明确说明在拉取请求(PR)获得批准之前需要完成的工作。
  • 如果要求您更新拉取请求并进行一些更改,则无需创建新的拉取请求。将您的更改推送到同一分支即可。
  • 提交者保留拒绝任何拉取请求(PR)的权利,在某些情况下可能会要求作者提交议题。

测试环境

  • Apache GitHub 组织的成员可以通过创建一个只包含命令 /testenv up 的评论,直接在拉取请求上启动一个临时测试环境。
    • 请注意,组织成员身份必须公开,此验证才能正常运行。
  • 可以通过在命令后指定特性标志名称(前缀为 FEATURE_)和值来为测试环境设置特性标志。
    • 格式:/testenv up FEATURE_<特性标志名称>=true|false
    • 示例:/testenv up FEATURE_DASHBOARD_NATIVE_FILTERS=true
    • 可以在单个命令中设置多个特性标志,用空格分隔
  • 工作流脚本将创建一个评论,其中包含临时环境的地址和登录信息。
  • 一旦拉取请求(PR)的 Docker 构建 CI 工作流成功完成,就可以创建测试环境。
  • 当新的提交添加到拉取请求时,测试环境目前不会自动更新。
  • 测试环境目前不支持异步工作器,但已在计划中。
  • 运行中的测试环境将在关闭拉取请求时关闭。

合并

  • 合并拉取请求(PR)至少需要一次批准。
  • 拉取请求(PR)通常在合并前至少保持开放 24 小时。
  • 拉取请求(PR)合并后,关闭相应的议题

合并后的责任

  • 如果拉取请求(PR)引入了新问题,项目维护者可能会联系拉取请求的作者。
  • 如果发现关键问题(例如破坏 master 分支 CI),项目维护者可能会撤销您的更改。

管理议题和拉取请求

为了处理传入的议题和拉取请求,提交者会阅读这些议题/拉取请求,并用标签进行分类,帮助贡献者找出需要采取行动的地方,因为贡献者通常拥有不同的专业知识。

分类目标

  • 对于议题: 分类、筛选议题、标记作者需要采取的行动。
  • 对于拉取请求(PR): 分类、标记作者需要采取的行动。如果拉取请求已准备好审查,则标记审查者需要采取的行动。

首先,添加类别标签(即哈希标签)。每个议题/拉取请求都必须有一个哈希标签(垃圾邮件条目除外)。以 # 开头的标签定义议题/拉取请求的类型

标签用于议题用于拉取请求
#bug错误报告错误修复
#code-quality描述代码、架构或生产力问题重构、测试、工具
#feature新功能请求新功能实现
#refine提出改进建议,例如调整内边距或优化 UI 样式,不包括新功能、错误修复和重构。实施改进,例如调整内边距或优化 UI 样式,不包括新功能、错误修复和重构。
#doc文档文档
#question故障排除:安装、本地运行、询问如何操作。稍后可改为 #bug不适用
#SIPSuperset 改进提案不适用
#ASF与 Apache 软件基金会政策相关的任务与 Apache 软件基金会政策相关的任务

然后酌情添加其他类型的标签。

  • 描述性标签(即点标签): 这些以 . 开头的标签描述议题/拉取请求的详细信息,例如 .ui.js.install.backend 等。每个议题/拉取请求可以有零个或多个点标签。
  • 需求标签: 这些标签的模式为 need:xxx,描述了进展所需的工作,例如 need:rebase(需要变基)、need:update(需要更新)、need:screenshot(需要截图)。
  • 风险标签: 这些标签的模式为 risk:xxx,描述了采纳此工作的潜在风险,例如 risk:db-migration(数据库迁移风险)。目的是为了更好地理解影响,并为需要更严格测试的拉取请求(PR)提高意识。
  • 状态标签: 这些标签描述状态(例如 abandoned(已放弃)、wontfix(不会修复)、cant-reproduce(无法复现)等)。被拒绝或未完成而关闭的议题/拉取请求应带有一个或多个状态标签。
  • 版本标签: 这些标签的模式为 vx.x,例如 v0.28。议题上的版本标签描述了报告错误时的版本。拉取请求(PR)上的版本标签描述了将包含该拉取请求的第一个发布版本。

如果作者提供的标题不够描述性,提交者也可以更新标题以反映议题/拉取请求的内容。

如果拉取请求(PR)通过了 CI 测试且没有任何 need: 标签,则表示已准备好审查,请添加 review 和/或 design-review 标签。

如果议题/拉取请求不活跃超过 30 天,它将被关闭。如果它没有任何状态标签,请添加 inactive

在创建拉取请求(PR)时,如果您的目标是将其包含在特定发布版本中,请为其添加版本标签。例如,要将拉取请求考虑纳入 Superset 1.1,请使用标签 v1.1

回滚指南

回滚导致 master 分支出现问题的更改是开发过程中的正常和预期部分。在开源社区中,更改的后果并非总能被完全理解。考虑到这一点,以下是一些在考虑回滚时需要牢记的因素:

  • 拉取请求作者的可用性: 如果原始拉取请求作者或合并代码的工程师高度可用,并能在合理的时间内提供修复,则这可能表明不应进行回滚。
  • 问题的严重性: master 分支上的问题有多严重?它是否阻碍了项目的进展?是否影响了用户?有多少比例的用户会遇到问题?
  • 回滚更改的大小: 回滚单个小型拉取请求(PR)比回滚大规模、多拉取请求的更改风险要低得多。
  • 回滚更改的“年龄”: 回滚最近合并的拉取请求(PR)比回滚较旧的拉取请求更容易接受。在一个较旧的拉取请求中发现的错误不太可能导致广泛的严重问题。
  • 回滚的固有风险: 回滚是否会破坏关键功能?此补救措施是否比问题本身更危险?
  • 制定修复方案的难度: 对于有明确解决方案的问题,可能更倾向于实现和合并修复,而不是进行回滚。

如果您决定回滚是可取的,执行回滚的贡献者有责任做到:

  • 联系相关方: 应联系拉取请求的作者和合并该工作的工程师,并告知他们回滚事宜。
  • 提供简洁的复现步骤: 确保拉取请求的原始作者能够清楚地理解并复现该问题。
  • 让回滚通过代码审查: 回滚必须得到另一位提交者的批准。

设计指南

大小写规范

句首大写

UI 中的所有内容都使用句首大写(除了这些 **)。

句首大写主要以小写为主。只将第一个单词的首字母大写,以及其他需要大写的单词,例如:

  • 专有名词。产品中的对象被视为专有名词,例如仪表板、图表、已保存的查询等。专有功能名称,例如 SQL Lab、Preset Manager 视为专有名词。
  • 缩写词(例如 CSS, HTML)
  • 在引用本身已大写的 UI 标签时(例如页面标题 - Dashboards 页面、Charts 页面、Saved queries 页面等)
  • 反映在 UI 中的用户输入。例如,用户命名的仪表板选项卡

句首大写 vs. 标题式大写: 标题式大写:“A Dog Takes a Walk in Paris” 句首大写:“A dog takes a walk in Paris”

为什么要用句首大写?

  • 普遍认为它阅读速度最快
  • 它是区分普通名词和专有名词最简单的方式

如何引用 UI 元素

在撰写有关 UI 元素的内容时,请使用 UI 中所用的大小写形式。

例如,如果一个输入字段标记为“Name”,那么您应将其称为“Name 输入字段”。同样,如果一个按钮上标有“Save”,那么将其称为“Save 按钮”是正确的。

如果产品页面标题为“Settings”,您在书面中应这样引用:“在 Settings 页面编辑您的个人信息”。

产品页面通常会与其中包含的对象具有相同的标题。在这种情况下,请按照 UI 中显示的页面名称引用页面,并将其中的对象作为普通名词引用

  • 在 Dashboards 页面上传仪表板
  • 前往 Dashboards
  • 查看仪表板
  • 查看所有仪表板
  • 在 CSS templates 页面上传 CSS 模板
  • 您保存的查询将显示在 Saved queries 页面
  • 在 SQL Lab 中创建自定义查询,然后创建仪表板

**句首大写的例外情况

  • 输入标签、按钮和 UI 选项卡全部大写
  • 用户输入值(例如列名、SQL Lab 选项卡名称)应保持其原始大小写

编程语言规范

Python

config.py 中的参数(可通过 Flask app.config 字典访问)假定始终已定义,因此应直接通过以下方式访问:

blueprints = app.config["BLUEPRINTS"]

而不是:

blueprints = app.config.get("BLUEPRINTS")

或类似方式,因为后者会导致类型问题。前者类型为 List[Callable],而后者类型为 Optional[List[Callable]]

类型注解 / 类型提示

为确保清晰度、一致性和可读性,所有新函数都应使用类型提示并包含文档字符串。

根据 PEP-484,没有提出明确列出抛出异常的语法,因此建议将此信息放入文档字符串中,即:

import math
from typing import Union


def sqrt(x: Union[float, int]) -> Union[float, int]:
"""
Return the square root of x.

:param x: A number
:returns: The square root of the given number
:raises ValueError: If the number is negative
"""

return math.sqrt(x)

TypeScript

TypeScript 受到完全支持,是编写所有新前端组件的推荐语言。在修改现有函数/组件时,我们鼓励迁移到 TypeScript,但并非强制要求。有关将函数/组件迁移到 TypeScript 的示例,请参见 #9162#9180