# 如何贡献 很高兴你能读到这篇文章,欢迎加入项目社区,帮助项目成长。 ## 发现 bug ? - **通过在 GitHub 的 [Issues](https://github.com/lf-edge/ekuiper/issues) 下搜索,确保该错误尚未被报告**。 - 如果你找不到解决该问题的公开问题,[开一个新的 Issue](https://github.com/lf-edge/ekuiper/issues/new)。请确保**标题和清晰的描述**,尽可能多的相关信息,以及**代码样本**或**可执行的测试案例**,以明确问题。 ## 代码和文档贡献 欢迎贡献代码以提供功能或修复错误。 ### 一次性设置 我们使用 GitHub pull request 来审查提议的代码修改。所以你需要在做出代码贡献之前拥有一个 GitHub 账户。 1. **Fork** eKuiper 到你的私人仓库。点击 eKuiper 仓库右上角的 "Fork "按钮。 2. 从你的个人分叉中**克隆**版本库。 `git clone https://github.com//ekuiper.git` 。 3. 添加 eKuiper repo 作为额外的 Git 远程仓库,这样你就可以在本地 repo 和 eKuiper 之间进行同步。 ```shell git remote add upstream https://github.com/lf-edge/ekuiper.git ``` 你可以使用你喜欢的 IDE 或编辑器来开发。你可以在 [Editors and IDEs for GO](https://github.com/golang/go/wiki/IDEsAndTextEditorPlugins) 中找到编辑器对 Go 工具的支持信息。 ### 创建一个分支 你将在你自己的 repo 中的一个分支中进行你的代码开发。创建一个本地分支,初始化为你希望合并到的分支的状态。`master` 分支是活跃的开发分支,所以建议将 `master` 设为基础分支。 ```shell $ git fetch upstream $ git checkout -b upstream/master ``` ### 包引入规范 合理的包引入顺序可以增强代码的整洁性和规范性。本项目使用 gci 自动检查包引入的顺序,优先级为 `标准包` > `第三方外部包` > `项目本地包`,如: ```go import ( "fmt" "github.com/sirupsen/logrus" "github.com/lf-edge/ekuiper/pkg/api" ) ``` 在项目根目录下,可以运行 `gci write --skip-generated -s standard -s default -s "prefix(github.com/lf-edge/ekuiper)" .` 命令自动重新排序包引入顺序。 或者如果你使用 GoLand,可以在 `Settings > Editor > Code Style > Go > Imports` 下勾选 `Group` 和 `Group stdlib imports` 以及相应的子选项来开启自动引入排序。 ### 代码惯例 - 在提交代码变更之前,使用 `go fmt` 来格式化你的代码。 - 使用 `make lint` 来运行静态代码分析以确保没有基本的格式或规范问题。 - 如果你遇到 `gofumpt` 相关的 lint 错误,直接在项目根目录运行 `gofumpt -w .` 即可解决。 - 其他 lint 相关的错误信息,请查看 [golangci-lint](https://golangci-lint.run/) 文档。 - 配置文件中的配置键使用 camel 大小写格式。 ### 调试你的代码 以 GoLand 为例,开发者可以对代码进行调试。 1. 调试整个程序。确保 [Makefile](https://github.com/lf-edge/ekuiper/blob/master/Makefile) build_prepare 部分提到的所有目录都在你的 eKuiper 根路径中创建。添加你的断点。打开 `cmd/kuiperd/main.go` 。在主函数中,你会发现标尺上有一个绿色的三角形,点击它并选择调试。然后创建你的流/规则,让它运行到你的断点,调试器会在那里暂停。 2. 要调试一小部分代码,我们建议写一个单元测试并调试它。你可以到任何一个测试文件中,找到同样的绿色三角形,在调试模式下运行。例如,`pkg/cast/cast_test.go` TestMapConvert_Funcs 可以作为调试运行。 #### 调试 edgex 代码 用户可以修改 edgex 源/目标代码以满足他们的要求。在这种情况下,最佳实践是让其他服务在 docker 模式下运行,但 eKuiper 在本地运行。 用户可以按照以下步骤设置环境 #### 暴露消息总线 eKuiper 按主题订阅消息,默认情况下,edgex 使用 redis 作为消息总线。本指南将使用 redis 作为示例来展示如何公开消息总线。 在 docker-compose 文件中,找到 redis 服务并在端口部分更改 127.0.0.1:6379 到 0.0.0.0:6379,然后重启所有服务。 ```yaml database: container_name: edgex-redis environment: CLIENTS_CORE_COMMAND_HOST: edgex-core-command CLIENTS_CORE_DATA_HOST: edgex-core-data CLIENTS_CORE_METADATA_HOST: edgex-core-metadata CLIENTS_SUPPORT_NOTIFICATIONS_HOST: edgex-support-notifications CLIENTS_SUPPORT_SCHEDULER_HOST: edgex-support-scheduler DATABASES_PRIMARY_HOST: edgex-redis EDGEX_SECURITY_SECRET_STORE: "false" REGISTRY_HOST: edgex-core-consul hostname: edgex-redis image: redis:6.2-alpine networks: edgex-network: {} ports: - 0.0.0.0:6379:6379/tcp read_only: true restart: always security_opt: - no-new-privileges:true user: root:root volumes: - db-data:/data:z ``` #### 修改本地 edgex 的配置 根据消息总线类型更改 edgex 源配置,下表为消息总线配置 该文件位于 `etc/sources/edgex.yaml` 中。 | message bus | type | protocol | server | port | |---------------|-------|----------|--------------|------| | redis server | redis | redis | 10.65.38.224 | 6379 | | mqtt broker | mqtt | tcp | 10.65.38.224 | 1883 | | zemo mq | zero | tcp | 10.65.38.224 | 5566 | 以 redis 为例,下面的配置会让 eKuiper 连接到 10.65.38.224 的 6379 端口。 ```yaml default: protocol: redis server: 10.65.38.224 port: 6379 topic: rules-events type: redis # Could be 'event' or 'request'. # If the message is from app service, the message type is an event; # Otherwise, if it is from the message bus directly, it should be a request messageType: event ``` 修改后 redis 会监听主机的 6379 端口,开发者可以通过服务器地址连接到 edgex 远程运行的机器。 例如机器 ip 地址为 10.65.38.224 ,用户可以通过该 ip 地址连接。 #### 打开 eKuiper 的控制台日志,修改 rest 端口 更改 `etc/kuiper.yaml` 中的配置文件,将控制台日志设置为 true 并将 eKuiper rest api 端口设置为 59720 ```yaml basic: # true|false, with debug level, it prints more debug info debug: false # true|false, if it's set to true, then the log will be print to console consoleLog: true # true|false, if it's set to true, then the log will be print to log file fileLog: true # How many hours to split the file rotateTime: 24 # Maximum file storage hours maxAge: 72 # CLI ip ip: 0.0.0.0 # CLI port port: 20498 # REST service ip restIp: 0.0.0.0 # REST service port restPort: 59720 # true|false, when true, will check the RSA jwt token for rest api authentication: false # restTls: # certfile: /var/https-server.crt # keyfile: /var/https-server.key # Prometheus settings prometheus: false prometheusPort: 20499 # The URL where hosts all of pre-build plugins. By default it's at packages.emqx.net pluginHosts: https://packages.emqx.net # Whether to ignore case in SQL processing. Note that, the name of customized function by plugins are case-sensitive. ignoreCase: true ``` #### run locally 使用前面提到的 [启动方法](./CONTRIBUTING.md#调试你的代码) 运行 eKuiper ### 测试 eKuiper 项目利用 Github actions 来运行单元测试和 FVT(功能验证测试),所以请看一下 PR 状态的运行结果,并确保所有的测试用例都能成功运行。 - 如果有必要,请编写 Golang 单元测试案例来测试你的代码。 - [FVT 测试案例](../../test/README.md) 将随着任何 PR 提交而被触发,所以请确保这些测试案例能够成功运行。 ### 许可 所有贡献给 eKuiper 的代码都将在 Apache License V2 下授权。你需要确保你添加的每个新文件都有正确的许可证头。 ### Sign-off Sign-off 是为了证明提交的来源。它是提交给这个项目的必要条件。如果你设置了 你的`user.name`和`user.email`的 git 配置,你可以用`git commit -s`自动签署你的提交。每次提交都必须签名。 ### 同步 在提交 PR 之前,你应该用目标分支的最新改动来更新你的分支。我们倾向于使用 rebase 而不是 merge,以避免不必要的合并提交。 ```shell git fetch upstream git rebase upstream/master ``` 假设你 forked repo 名称是默认的`origin`, 使用如下指令推送改动到你的 forked repo。假设你 forked repo 名称是默认的`origin`。如果你在最后一次推送前重新建立了 git 历史,请添加 `-f` 来强制推送这些变化。 ```shell git push origin -f ``` ### 提交修改 `master` 分支是活跃的开发分支,所以建议将 `master` 设为基础分支,并在 `master` 分支下创建 PR 组织你的提交,使提交者在审查时更容易。提交者通常喜欢多个小的拉动请求,而不是一个大的拉动请求。在一个拉动请求中,最好有相对较少的提交,将问题分解成合理的步骤。对于大多数 PR ,你可以将你的修改压缩到一个提交。你可以使用下面的命令来重新排序、合并、编辑或改变单个提交的描述。 ```shell git rebase -i upstream/master ``` 确保你的所有提交都符合 [提交信息指南](#提交信息指南)。 然后你会推送到你 forked 的 repo 上的分支,然后导航到 eKuiper repo 创建一个 PR 。我们的 GitHub repo 提供了基于 GitHub actions 的自动化测试。请确保这些测试通过。我们将在所有测试通过后审查代码。 ### 提交信息指南 每条提交信息都由一个 **header** ,一个 **body** 和一个 **footer** 组成。header 包含三个部分:**类型**,**范围**和**主题**。 ```text <类型>(<范围>): <主题> <空行> <空行>