指南
Pull Request 指南
我们强烈鼓励的一种理念是
在创建 PR 之前,先创建一个 issue。
目的是将问题与可能的解决方案分开。
Bug 修复: 如果你只是修复一个小 bug,可以直接提交 pull request,但我们强烈建议提交一个详细描述你正在修复的 issue。这有助于在我们不接受那个特定修复但希望跟踪 issue 的情况下。请记住,项目维护者保留接受或拒绝传入的 PR 的权利,所以最好将 issue 和修复它的代码分开。在某些情况下,项目维护者可能会要求你在继续之前从 PR 创建一个单独的 issue。
重构: 对于小的重构,它可以是一个独立的 PR,详细说明你正在重构的内容以及原因。如果有疑虑,项目维护者可能会要求你在继续之前为 PR 创建一个 #SIP
。
功能/大改动: 如果你打算更改公共 API,或者对实现进行任何非平凡的更改,我们要求你将新 issue 作为 #SIP
(Superset 改进提案)提交。这让我们在你投入大量精力之前就你的提议达成一致。欢迎你与 SIP 一起提交 PR(有时这是必要的演示),但在 SIP 批准之前我们不会 review/merge 代码。
一般来说,小的 PR 总是比大的 PR 更容易 review。最佳做法是将你的工作分解成更小的独立 PR,并引用同一个 issue。这将大大减少周转时间。
如果你想分享你的尚未准备好 merge 的工作,可以创建一个 Draft PR。这将使维护者和 CI runner 能够优先考虑成熟的 PR。
最后,永远不要提交一个会使 master 分支处于损坏状态的 PR。如果 PR 是完成大型功能的多个 PR 的一部分且不能独立工作,你可以在创建从 feature 分支到 master 的 PR 之前创建一个 feature 分支并将所有相关的 PR 合并到 feature 分支中。
协议
编写
-
填写 PR 模板的所有部分。
-
使用以下语义前缀之一来命名 PR(受 Karma 启发):
feat
(新功能)fix
(bug 修复)docs
(文档变更)style
(格式化,缺少分号等;无应用程序逻辑变更)refactor
(重构代码)test
(添加缺失的测试,重构测试;无应用程序逻辑变更)chore
(更新任务等;无应用程序逻辑变更)perf
(性能相关变更)build
(构建工具,Docker 配置变更)ci
(测试运行器,GitHub Actions 工作流变更)other
(不符合上述情况的变更——应该很少见!)- 示例:
feat: export charts as ZIP files
perf(api): improve API info performance
fix(chart-api): cached-indicator always shows value is cached
-
如果尚未准备好审核,请在标题前加上
[WIP]
前缀(WIP = work-in-progress)。我们建议首先创建带有[WIP]
的 PR,并在至少一次通过 CI 测试并阅读过你的代码更改后删除它。 -
如果你认为你的 PR 引入了潜在的破坏性变更,在 PR 标题中的语义前缀后但冒号前加上
!
,如:feat!: Added foo functionality to bar
-
截图/GIF: 用户界面的更改需要 before/after 截图,或 GIF 用于交互
-
依赖项: 添加新依赖项时要小心,并避免不必要的依赖项。
- 对于 Python,将其包含在
pyproject.toml
中,指出任何特定限制,并 在requirements.txt
中固定到特定版本,以确保应用程序构建是确定性的。 - 对于 TypeScript/JavaScript,将新库包含在
package.json
中
- 对于 Python,将其包含在
-
测试: Pull request 应包含测试,无论是 doctests、unit tests 还是两者都有。确保解决所有错误和测试失败。参见测试了解如何运行测试。
-
文档: 如果 pull request 添加了功能,则应在同一 PR 中更新文档。
-
CI: 审查者在所有 CI 测试通过之前不会审查代码。有时可能会有不稳定测试。你可以关闭并重新打开 PR 以重新运行 CI 测试。如果问题持续存在,请报告。在 CI 修复部署到
master
后,请 rebase 你的 PR。 -
代码覆盖率: 请确保代码覆盖率不会降低。
-
当准备审核时移除
[WIP]
。请注意,批准后可能会很快合并,因此请确保 PR 已准备好合并,并且不要期望批准后有更多时间进行编辑。 -
如果 PR 尚未准备好审核并且超过 30 天未活动,我们将因未活动而关闭它。作者可以重新打开并更新。
审核
- 写评论时使用建设性的语气。
- 如果需要更改,清楚地说明在 PR 可以被批准之前需要做什么。
- 如果被要求用一些更改更新你的 PR,不需要创建一个新的。将你的更改推送到同一个分支。
- 提交者保留拒绝任何 PR 的权利,在某些情况下可能会要求作者提交一个 issue。
测试环境
- Apache GitHub 组织的成员可以通过创建包含(only)命令
/testenv up
的评论直接在 PR 上启动临时测试环境。- 注意,为了使此验证正常工作,组织成员身份必须公开。
- 可以通过在命令后指定标志名称(以
FEATURE_
为前缀)和值来为测试环境设置特性标志。- 格式:
/testenv up FEATURE_<feature flag name>=true|false
- 示例:
/testenv up FEATURE_DASHBOARD_NATIVE_FILTERS=true
- 单个命令中可以设置多个特性标志,以空格分隔
- 格式:
- 工作流程脚本将创建一个评论,其中包含临时环境的地址和登录信息。
- 可以在 PR 的 Docker 构建 CI 工作流程成功完成后创建测试环境。
- 当向 PR 添加新提交时,测试环境目前不会自动更新。
- 测试环境目前不支持 async workers,尽管这正在计划中。
- 关闭 PR 时将关闭运行中的测试环境。
合并
- 合并 PR 至少需 要一个批准。
- PR 通常在合并前至少保持打开 24 小时。
- PR 合并后,关闭相应的 issue。
后合并责任
- 如果 PR 引入了新问题,项目维护者可能会联系 PR 作者。
- 如果发现关键问题,例如破坏 master 分支 CI,项目维护者可能会撤销你的更改。
管理 Issues 和 PRs
为了处理进来的 issues 和 PRs,提交者阅读 issues/PRs 并用标签标记它们, 以便分类并帮助贡献者找到采取行动的地方,因为贡献者通常具有不同的专长。
分类目标
- 对于 issues: 分类,筛选 issues,标记作者所需的操作。
- 对于 PRs: 分类,标记作者所需的操作。如果 PR 已准备好审核,标记审查者所需的操作。
首先,添加 类别标签(也称为 hash 标签)。每个 issue/PR 都必须有一个 hash 标签(除了垃圾条目)。
以 #
开头的标签定义 issue/PR 类型:
Label | for Issue | for PR |
---|---|---|
#bug | Bug 报告 | Bug 修复 |
#code-quality | 描述代码、架构或生产力的问题 | 重构、测试、工具 |
#feature | 新功能请求 | 新功 能实现 |
#refine | 提出改进,如调整填充或细化 UI 样式,不包括新功能、Bug 修复和重构。 | 实现改进,如调整填充或细化UI样式,不包括新功能、Bug修复和重构。 |
#doc | 文档 | 文档 |
#question | 故障排除:安装、本地运行、询问如何做某事。稍后可更改为 #bug 。 | N/A |
#SIP | Superset 改进提案 | N/A |
#ASF | 与 Apache 软件基金会政策相关的任务 | 与 Apache 软件基金会政策相关的任务 |
然后根据需要添加其他类型的标签。
- Descriptive(描述性)标签(也称为点标签): 这些以
.
开头的标签描述了 issue/PR 的细节,如.ui
、.js
、.install
、.backend
等。每个 issue/PR 可以有零个或多个点标签。 - Need(需要)标签: 这些标签具有模式
need:xxx
,描述了继续进行所需的工作,如need:rebase
、need:update
、need:screenshot
。 - Risk(风险)标签: 这些标签具有模式
risk:xxx
,描述了采纳工作的潜在风险,如risk:db-migration
。其目的是更好地理解影响,并提高对需要更严格测试的 PR 的认识。 - Status(状态)标签: 这些标签描述了状态(
abandoned
、wontfix
、cant-reproduce
等)。被拒绝或未完成就关闭的 issue/PR 应该有一个或多个状态标签。 - Version(版本)标签: 这些具有模式
vx.x
,如v0.28
。在 issue 上的版本标签描述了报告 bug 的版本。在 PR 上的版本标签描述了将包含 PR 的第一个发布。
提交者也可以更新标题以反映 issue/PR 的内容,如果作者提供的标题不够描述性。
如果 PR 通过了 CI 测试并且没有任何 need:
标签,它就可以接受审核,添加 review
和/或 design-review
标签。
如果 issue/PR 在 >=30 天内没有活动,它将被关闭。如果没有状态标签,添加 inactive
。
在创建 PR 时,如果你希望将其包含在特定版本中,请用版本标签标记它。例如,要让 PR 考虑包含在 Superset 1.1 中,使用标签 v1.1
。
撤销指南
在主分支中撤销引起问题的更改是开发过程中的正常且预期的部分。在开源社区中,更改的影响并不总是可以完全理解。考虑到这一点,以下是考虑撤销时需要记住的一些考虑因素:
- PR 作者的可用性: 如果原始 PR 作者或合并代码的工程师高度可用,并且可以在合理的时间框架内提供修复,这会反指撤销。
- Issue 的严重性: 主分支上的问题有多严重?它是否阻碍了项目的进展?是否有用户影响?有多少百分比的用户会遇到问题?
- 要撤销的更改 Size: 撤销单个小 PR 的风险远低于撤销大规模、多 PR 更改。
- 要撤销的更改 Age: 撤销最近合并的 PR 比撤销旧 PR 更可接受。在旧 PR 中发现的 bug 不太可能造成广泛严重的问题。
- 撤销固有的 Risk: 撤销是否会破坏关键功能?治疗是否比疾病更危险?
- 制定修复的 Difficulty: 在问题有明确解决方案的情况下,实施 并合并修复可能比撤销更可取。
如果你决定撤销是可取的,执行撤销的贡献者的责任是:
- 联系利益相关方: 应该联系 PR 的作者和合并工作的工程师,并告知他们撤销的情况。
- 提供简洁的复现步骤: 确保问题可以被 PR 的原始作者清晰理解和复制。
- 将撤销通过代码审核: 撤销必须由另一位提交者批准。
设计指南
大写指南
句子大小写
对于 UI 中的所有内容(除了这些 **),使用句子大小写。
句子大小写主要是小写。仅大写第一个单词的首字母,以及需要大写的其他单词,如:
- 专有名词。 产品中的对象 are not 被视为专有名词,例如 dashboards, charts, saved queries 等。专有特性名称,例如 SQL Lab、Preset Manager 被视为 专有名词
- 缩写(例如 CSS、HTML)
- 当从句子大小写提及 本身大写的 UI 标签 时(例如页面标题 - Dashboards page, Charts page, Saved queries page 等)
- 显示在 UI 中的用户输入。例如,用户命名的一个仪表板选项卡
句子大小写与标题大小写: 标 题大小写: "A Dog Takes a Walk in Paris(一只狗在巴黎散步)" 句子大小写: "A dog takes a walk in Paris"
为什么使用句子大小写?
- 它通常被认为是最容易阅读的
- 它是最容易区分常用名词和专有名词的形式
如何引用 UI 元素
在撰写关于 UI 元素时,使用与 UI 中相同的大小写。
例如,如果输入字段标有 “Name”,则将其称为 “Name input field”。同样,如果按钮上带有 “Save” 的标签,则正确地将其称为 “Save button”。
当产品页面标题为 “Settings” 时,您应按以下方式书写: “Edit your personal information on the Settings page”。
通常,产品页面的标题与其包含的对象相同。在这种情况下,按照 UI 中显示的方式引用页面,将对象作为普通名词引用:
- Upload a dashboard on the Dashboards page(在仪表板页面上上传一个仪表板)
- Go to Dashboards(前往仪表板)
- View dashboard(查看仪表板)
- View all dashboards(查看所有仪表板)
- Upload CSS templates on the CSS templates page(在 CSS 模板页面上上传 CSS 模板)
- Queries that you save will appear on the Saved queries page(您保存的查询将出现在保存的查询页面上)
- Create custom queries in SQL Lab then create dashboards(在 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]]
。
类型 / 类型提示
为了确保清晰度、一致性以及所有可读性,所有 新函数 都应该使用 type hints 并且包含一个 docstring。
根据 PEP-484 的说明, 没有提出明确列出抛出异常的语法,因此建议将这些信息放在 docstring 中,即,
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 中找到。