我们在日常工作中经常会使用到很多的开源项目,开源也是一个在工作和学习中都离不开的内容。一般来说,开源项目可以选择直接开源,也可以选择捐赠给某些基金会,例如 Linux FoundationCNCFASF 等等。以 ASF 为例,如果一个项目想要成为 顶级项目,则需要先通过 孵化器 孵化,孵化结束毕业才能成为顶级项目。最近我因为一些原因参与了云原生网关 APISIX 开源项目,这里做一下介绍。

搭建环境

首先我们需要下载源代码并且构建开发流程,根据 官网介绍,我们把项目代码 fork 到自己的仓库并 clone 到本地,随后在本地仓库中将原始的项目设置为上游upstream,之后新建分支进行开发即可

~ git clone git@github.com:RitterHou/apisix.git
~ cd apisix
~ git remote -v
~ git remote add upstream https://github.com/apache/apisix.git
~ git config --global user.name "derobukal"
~ git config --global user.email "derobukal@gmail.com"
~ git fetch upstream
~ git checkout master
~ git rebase upstream/master
~ git push origin master
~ git checkout -b issue-10484
~ cd ..

根据 官方教程,我们还需要安装 APISIX 的开发环境注 1

~ export https_proxy="http://192.168.65.100:7890"
~ export http_proxy="http://192.168.65.100:7890"
~ wget https://raw.githubusercontent.com/apache/apisix/master/utils/install-dependencies.sh
~ APISIX_RUNTIME='1.1.1' bash install-dependencies.sh
~ cd apisix
~ make deps
~ sudo mkdir /usr/local/apisix
~ sudo mkdir /usr/local/apisix/logs
~ sudo chown raymond:raymond /usr/local/apisix -R
~ sudo make install

以及安装和启动 etcd

~ ETCD_VERSION='3.4.18' wget https://github.com/etcd-io/etcd/releases/download/v${ETCD_VERSION}/etcd-v${ETCD_VERSION}-linux-amd64.tar.gz && tar -xvf etcd-v${ETCD_VERSION}-linux-amd64.tar.gz && cd etcd-v${ETCD_VERSION}-linux-amd64 && sudo cp -a etcd etcdctl /usr/bin/
~ cd ..
~ etcd

最简单的 PR

搭建好了环境之后,就可以修改代码并提交 PR 了。一般来说开源项目都会有多种类型的改动,以 apisix 为例,它限制了 PR 可以为 固定的几种类型

feat
fix
docs
style
refactor
perf
test
build
ci
chore
revert
change

包含了文档修改、新功能、bug 修复等等,我们选择比较简单的文档修改作为第一个 PR。我在使用 APISIX 的过程中,发现它 证书相关的文档 中存在一个错误

在上图中,这里的地址不应该是/hello而应该是/get,因此我们可以在本地仓库新建一个分支并对这个问题作出修改。修改后我们将这次改动提交(为了使提交更加的清晰和安全,建议 合并 commit 并对 commit 进行签名)并 push 到我们自己的远程仓库,随后在 GitHub 上面创建一个针对 原始仓库的 Pull Request。一般项目在创建一个 PR 的时候都会有模板信息,照着模板信息进行填写即可,填写完毕就可以提交 PR 并等待项目的成员进行处理了

修复 issue 中的问题

在 APISIX 中有着很多的 ISSUE

我们可以关注这些 ISSUE 看有没有自己能解决的问题。一般来说,带有good first issue标签的都是比较简单并且适合新人的,我们可以优先从这些 issue 中寻找自己能解决的问题

在确定了 issue 之后,我们可以请求管理员将这个 issue 分配给自己,防止别人也会去解决这个问题从而浪费时间。当然,有的时候 issue 即使已经被分配给别人了,但是如果他一直没有解决这个问题,我们仍然可以请求将这个 issue 分配给自己

搭建测试环境

对于 issue-10484,因为涉及到代码更改,因此需要执行测试。APISIX 使用了 test-nginx 框架来执行测试,官方有关于如何进行测试的介绍

我们需要安装测试框架注 2

sudo cpan Test::Nginx

并下载依赖测试模块

➜  apisix git:(issue-10484) git clone https://github.com/api7/test-toolkit/ t/toolkit

修改完代码之后可以执行相关的测试

~ PATH=/usr/local/openresty/nginx/sbin:/usr/bin PERL5LIB=.:$PERL5LIB FLUSH_ETCD=1 prove -Itest-nginx/lib -r t/admin/ssl2.t
t/admin/ssl2.t .. ok    
All tests successful.
Files=1, Tests=52, 11 wallclock secs ( 0.06 usr  0.01 sys +  3.61 cusr  1.05 csys =  4.73 CPU)
Result: PASS

如果测试没有问题就可以提交 PR 了。

通过 CI 的测试

apisix 使用 GitHub 的 workflow 进行 CI 执行测试,以 redhat-ci.yaml 为例,它会在多个平台上执行多个文件夹内的测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
jobs:
test_apisix:
name: run ci on redhat ubi
runs-on: ubuntu-20.04
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
events_module:
- lua-resty-worker-events
- lua-resty-events
test_dir:
- t/plugin/[a-k]*
- t/plugin/[l-z]*
- t/admin t/cli t/config-center-yaml t/control t/core t/debug t/discovery t/error_page t/misc
- t/node t/pubsub t/router t/script t/secret t/stream-node t/utils t/xds-library

如上所示,GitHub action 中的 matrix 默认会对其下面的的多个选项进行合并,例如redhat-ci.yamlevents_moduletest_dir组合起来就会构成 8 个执行脚本

lua-resty-worker-events t/plugin/[a-k]*
lua-resty-worker-events t/plugin/[l-z]*
lua-resty-worker-events t/admin t/cli t/config-center-yaml t/control t/core t/debug t/discovery t/error_page t/misc
lua-resty-worker-events t/node t/pubsub t/router t/script t/secret t/stream-node t/utils t/xds-library
lua-resty-events t/plugin/[a-k]*
lua-resty-events t/plugin/[l-z]*
lua-resty-events t/admin t/cli t/config-center-yaml t/control t/core t/debug t/discovery t/error_page t/misc
lua-resty-events t/node t/pubsub t/router t/script t/secret t/stream-node t/utils t/xds-library

github 的 CI 会对这些所有的任务执行测试。如果测试执行失败了,需要重点关注失败的日志,并在本地调试直到可以通过测试。如果遇到数据不对的问题,可以重新对数据进行初始化

apisix quit && apisix init && apisix init_etcd && apisix start

社区交流

在代码提交并创建了 PR 之后,我们可能会收到一些反馈,这时候我们就需要针对这些反馈作出回应。以 #10771 为例

我在提交了代码之后,管理员认为需要将aes_encrypt_pkeyaes_decrypt_pkey方法中的field字段去掉。我一开始在写代码的时候就发现这个字段去掉会导致数据加解密过程中ssldata的行为不一致,可能导致错误。不过管理员让我放心删,没问题,本着信任的态度我就把参数删除掉了

但是删除掉了之后测试却怎么也跑不过,我因为非常信任社区管理员也没有怀疑是因为ssldata逻辑不一致导致的,而是从其它地方入手进行排查。最终花了大量的时间经过了很多**的排查之后,发现其实就是因为ssldata的行为逻辑不一致导致的。我随后询问了管理员,并且把field参数加了回来

field参数加回来之后,所有的 test cases 就都能跑过了

所有测试用例通过,一段时间之后 PR 被 review 没有问题,就会被合并到 master 分支了

参考

Revolution OS
S04E00-吴晟:开源项目进入 Apache 孵化器意味着什么
Apache 是如何运作的?
新手如何快速参与开源项目
如何从小白成长为 Apache Committer?

  1. 在执行install-dependencies.sh脚本的时候,会下载 golang 的依赖,比如 gRPC-Go,这里需要保证网络能够顺畅访问 golang 的官方仓库。

  2. 为了保证 test-nginx 正常安装,需要网络顺畅,能够正常访问相关资源。