Skip to main content
Edit this page on GitHub

指南

拉取请求指南

我们强烈鼓励的一种理念是:

在创建 PR 之前,先创建一个 Issue。

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

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

重构: 对于小的重构,可以作为一个独立的 PR,详细说明你正在重构的内容和原因。如果有疑问,项目维护者可能会要求你在继续之前为 PR 创建一个 #SIP

功能/重大变更: 如果你打算更改公共 API,或者对实现进行任何非平凡的更改,我们要求你提交一个新的 #SIP(Superset 改进提案)Issue。这让我们在你投入大量精力之前,就能对你的提案达成一致。你可以提交一个带有 SIP 的 PR(有时需要用于演示),但在 SIP 被批准之前,我们不会审查/合并代码。

一般来说,小的 PR 总是比大的 PR 更容易审查。最佳实践是将你的工作分解成较小的独立 PR,并引用同一个 Issue。这将大大减少周转时间。

如果你想分享尚未准备好合并的工作,可以创建一个 Draft PR。这将使维护者和 CI 运行者优先处理成熟的 PR。

最后,永远不要提交一个会让主分支处于损坏状态的 PR。如果 PR 是完成一个大功能的多个 PR 的一部分,并且不能独立工作,你可以创建一个功能分支,并将所有相关的 PR 合并到该功能分支中,然后再从功能分支创建一个 PR 到主分支。

协议

作者

  • 填写 PR 模板的所有部分。

  • 使用以下语义前缀之一为 PR 命名(灵感来自 Karma):

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

  • 如果你认为你的 PR 贡献了一个潜在的破坏性变更,请在语义前缀后但在冒号前加上 !,例如:feat!: 为 bar 添加了 foo 功能

  • 截图/GIF: 用户界面的变更需要提供前后截图,或用于交互的 GIF

    • 推荐的捕捉工具(KapLICEcapSkitch
    • 如果没有提供截图,提交者将用 need:screenshot 标签标记 PR,并且在提供截图之前不会进行审查。
  • 依赖项: 小心添加新依赖项,并避免不必要的依赖项。

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

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

  • CI: 审查者不会审查代码,直到所有 CI 测试都通过。有时可能会有不稳定的测试。你可以关闭并重新打开 PR 以重新运行 CI 测试。如果问题持续存在,请报告。在 CI 修复部署到 master 后,请重新基于你的 PR。

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

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

  • 如果 PR 未准备好审查且超过 30 天未活动,我们将因不活动而关闭它。作者可以重新打开并更新。

审查

  • 在撰写审查意见时使用建设性的语气。
  • 如果有需要更改的地方,请明确说明在 PR 被批准之前需要完成的工作。
  • 如果你被要求更新你的 PR,无需创建新的 PR。将更改推送到同一分支。
  • 提交者保留拒绝任何 PR 的权利,在某些情况下可能会要求作者提交问题。

测试环境

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

合并

  • 至少需要一次批准才能合并 PR。
  • PR 通常在合并前至少开放 24 小时。
  • PR 合并后,关闭相应的问题

合并后的责任

  • 如果 PR 引入了新问题,项目维护者可能会联系 PR 作者。
  • 如果发现关键问题,例如破坏主分支 CI,项目维护者可能会回滚你的更改。

管理问题和 PR

为了处理不断涌入的问题和 PR,提交者会阅读问题/PR 并使用标签对其进行分类,以帮助贡献者识别需要采取行动的地方,因为贡献者通常有不同的专业领域。

分类目标

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

首先,添加 类别标签(也称为哈希标签)。每个问题/PR 必须有一个哈希标签(垃圾邮件条目除外)。以 # 开头的标签定义了问题/PR 的类型:

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

然后根据需要添加其他类型的标签。

  • 描述性标签(也称为点标签): 这些以 . 开头的标签描述了问题/PR 的细节,例如 .ui.js.install.backend 等。每个问题/PR 可以有零个或多个点标签。
  • 需求标签: 这些标签的模式为 need:xxx,描述了推进工作所需的工作,例如 need:rebaseneed:updateneed:screenshot
  • 风险标签: 这些标签的模式为 risk:xxx,描述了采用该工作可能存在的潜在风险,例如 risk:db-migration。目的是更好地理解影响,并为需要更严格测试的 PR 提高意识。
  • 状态标签: 这些标签描述了状态(abandonedwontfixcant-reproduce 等)。被拒绝或关闭而未完成的问题/PR 应有一个或多个状态标签。
  • 版本标签: 这些标签的模式为 vx.x,例如 v0.28。问题上的版本标签描述了报告错误的版本。PR 上的版本标签描述了将包含该 PR 的第一个发布版本。

如果作者提供的标题不够描述性,提交者也可以更新标题以反映问题/PR 的内容。

如果 PR 通过了 CI 测试并且没有任何 need: 标签,则它已准备好进行审查,添加标签 review 和/或 design-review

如果一个问题/PR 已经不活跃 >=30 天,它将被关闭。如果没有状态标签,添加 inactive

在创建 PR 时,如果您希望将其包含在特定版本中,请使用版本标签进行标记。例如,要使 PR 被考虑包含在 Superset 1.1 中,请使用标签 v1.1

回滚指南

回滚在主分支中引起问题的更改是开发过程中的正常且预期的一部分。在开源社区中,更改的影响并不总是能够完全理解。考虑到这一点,以下是考虑回滚时需要记住的一些注意事项:

  • PR 作者的可用性: 如果原始 PR 作者或合并代码的工程师高度可用,并且可以在合理的时间内提供修复,这将不利于回滚。
  • 问题的严重性: 主分支上的问题有多严重?它是否阻碍了项目的进展?是否有用户受到影响?有多少百分比的用户会遇到问题?
  • 被回滚更改的大小: 回滚一个单一的小 PR 的风险远低于回滚一个大规模的多 PR 更改。
  • 被回滚更改的年龄: 回滚最近合并的 PR 将比回滚较旧的 PR 更易接受。在较旧的 PR 中发现的错误不太可能引起广泛的严重问题。
  • 回滚固有的风险: 回滚会破坏关键功能吗?治疗方法比疾病更危险吗?
  • 制定修复的难度: 在问题有明确解决方案的情况下,可能更倾向于实施并合并修复而不是回滚。

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

  • 联系相关方: PR 的作者和合并工作的工程师都应被联系并告知回滚。
  • 提供简洁的复现步骤: 确保问题可以被 PR 的原作者清楚地理解和复现。
  • 通过代码审查进行回滚: 回滚必须由另一位提交者批准。

设计指南

大小写指南

句子大小写

在 UI 中使用句子大小写(除了这些 **)。

句子大小写主要是小写的。仅大写第一个单词的首字母和其他需要大写的单词,例如:

  • 专有名词。 产品中的对象(如仪表盘、图表、保存的查询等)不被视为专有名词。而专有功能名称(如SQL Lab、Preset Manager)则被视为专有名词。
  • 缩略词(例如CSS、HTML)
  • 当提及本身为大写的UI标签时,从句子格式(例如页面标题 - 仪表盘页面、图表页面、保存的查询页面等)
  • 在UI中反映的用户输入。例如,用户命名了一个仪表盘标签

句子格式与标题格式: 标题格式:"A Dog Takes a Walk in Paris" 句子格式:"A dog takes a walk in Paris"

为什么选择句子格式?

  • 通常被认为是阅读速度最快的格式
  • 最容易区分普通名词和专有名词

如何引用UI元素

在描述UI元素时,使用与UI中相同的格式。

例如,如果一个输入字段被标记为“名称”,那么你将其称为“名称输入字段”。同样,如果一个按钮的标签是“保存”,那么将其称为“保存按钮”是正确的。

如果一个产品页面标题为“设置”,你在写作中可以这样引用: “在设置页面编辑您的个人信息”。

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

  • 在仪表盘页面上上传仪表盘
  • 前往仪表盘
  • 查看仪表盘
  • 查看所有仪表盘
  • 在CSS模板页面上上传CSS模板
  • 您保存的查询将出现在保存的查询页面上
  • 在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中找到。