Szhangbiao's blog

记录一些让自己可以回忆的东西

0%

Firebase Remote Config的工程化案例

Config 工程化的灵感是来自于澳洲体育视频项目,他们的 Remote Config 工程化做的非常好,它分为两大类 Config 和 Storage,然后用 CircleCI 来自动化处理 Config 的更新和 Storage 的文件上传,是由运维人员来实现的,具体实现细节不是很清楚,所以这里我们来实现一个基于 Python 的 Config 工程化的案例。

最初方案

经过一番搜索我们得到一个接近的方案,具体可参考 这里,链接里提供了三个文件

1
2
3
cd.yaml // 主要放在项目根目录下的 ".github/workflows/"下 用于当 git push 时自动发布
config_manage.py // Python 可执行文件
requirement.txt // 根据txt文件里的声明通过 pip 安装依赖

下面我们依次对这三个文件进行说明
cd.yaml:

1
2
3
4
5
6
7
8
9
Build阶段:
1.安装Python,版本是 3.8
2.把requirement.txt文件设置到缓存
3.安装requirement.txt里声明的依赖
发布阶段:
需要Build阶段执行完后再执行
1.安装Python,版本是 3.8
2.安装requirement.txt里声明的依赖
3.把PROJECT_ID和CREDENTIALS设置到环境变量并运行config_manage.py 的publish方法

config_manage.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
def _get_access_token():
// 根据oauth2client库的api和环境变量里的凭证去获取 access token
...

def _get(save=False):
// 通过requests库用access token获取Remote Config并写入本地config.json文件
...

def _listVersions():
// 通过requests库用access token获取Remote Config最近修改的5个版本号
...

def _rollback(version):
// 通过requests库用access token撤回Remote Config到指定版本
...

def _publish():
// 把本地"remoteconfig.template.json"的内容push到远程
...

def main():
//通过接受的参数执行相应的方法
...

requirement.txt:

1
2
3
oauth2client // Google获取授权的python库
requests // 用于进行Api请求
python-dotenv // 用户获取系统变量里的值

这个方案并不能解决我们的实际需求,config_manage.py 里的方法相对比较单一,但是给了我们方向,增大了我们方案实现可行性

改造实现

经过我们的改造,工程的目录结构如下:

1
2
3
4
5
6
7
8
9
10
11
config-example
├── .github
│ └── workflows
│ └── deploy.yaml // Github Actions 配置文件
├── remote_config
│ └── configs.json // 各种Remote Config的json文件
├── storage
│ └── files // 需要上传到Firebase Storage的文件
├── remoteconfig.template.json
├── config_manage.py
└── requirement.txt

对于config_manage.py文件我们增加一个validation()方法并改造publish()以满足我们的需求
config_manage.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...

def _validation():
1.调用_get()方法并把ETag缓存起来
2.扫描remote_config目录,把多个json文件合并成符合Remote Config规则的remoteconfig.template.json文件
3.使用requests库调用 validate api 来验证remoteconfig.template.json文件是否符合Remote Config规则
...

def _publish():
1.调用_validation()方法检查json文件
2.使用requests库把"remoteconfig.template.json"的内容push到远程
...

def main():
//通过接受的参数执行相应的方法
...

我们这里也修改了 deploy 的触发条件,改为pull_request的时候触发,也就是在pull_request时,会自动发布。

后续优化

由于每次发布 config 都需要 PR,当一个人开发时还是比较繁琐,这里我们 copy 一份config_manage.py命名为config_manage_local.py,并把 Firebase 工程的account.json放到本地,然后在config_manage_local.py里修改 PROJECT_ID 和 credentials 的读取方式,这样就可以在命令行里直接发布 Remote Config。
最后工程目录结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
config-example
├── .github
│ └── workflows
│ └── deploy.yaml // Github Actions 配置文件
├── account_key // 把当前目录加入.gitignore,防止上传到Github
│ └── account.json
├── remote_config
│ └── configs.json // 各种Remote Config的json文件
├── storage
│ └── files // 需要上传到Firebase Storage的文件
├── remoteconfig.template.json
├── config_manage.py
├── config_manage_local.py
└── requirement.txt

跟之前项目的 Config 工程相比,我们的工程化更加灵活,Conbine jsons to template 的逻辑还可以根据后期的需求进行调整。

Firebase Storage 的 Deploy

Firebase Sotrage 文件上传就很简单了,只需要在.github/workflows/定义 yaml 文件,具体如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
name: Upload files to Cloud Storage

on:
pull_request:
branches:
- deploy/uat-storage
- deploy/prod-storage

jobs:
upload:
runs-on: ubuntu-latest

permissions:
contents: 'read'
id-token: 'write'
steps:
- id: 'checkout'
uses: 'actions/checkout@v3'

- id: 'auth'
uses: 'google-github-actions/auth@v1'
with:
credentials_json: ${{ secrets.CREDENTIALS }}

- id: 'upload-folder'
uses: 'google-github-actions/upload-cloud-storage@v1'
with:
path: './storage'
destination: '这里填写你的Bucket'
process_gcloudignore: false

到这里 Firebase Remote Config 和 Storage 的工程化就完成了,后续会考虑把 storage  里的文件部署到 Amazon S3,应该只需要添加一个 yaml 文件即可。