利用流水线实现版本一键发布
目录
- 1. 背景
- 2. 实现步骤
- 3.1 前置条件
- 3.2 更新版本号和拉出发布分支
- 3.3 生成 diffCommit
- 3.4 自动触发联动编译
- 3.5 让通知更友好
- 3. 总结
1. 背景
通常我们发布版本时会有这样几个步骤,更改版本号,拉出 release 分支,生成发布包。但是博主所在的项目组有点特殊,整个项目分为两个工程,Unity 工程和 Android 工程,需要 unity 工程打出 aar 包,Android 工程引用这个 aar,然后生成 apk。
所以我们发版的时候会有以下一些步骤:
- 在主干分支上更新 Android 工程的 version_code 和 version_name;
- 拉出 Android 的发布分支;
- 拉出 Unity 的发布分支;
- 生成 Unity 的 aar 包,并更新到对应的 Android 发布分支上;
- 打出 apk;
- 记录当前发布分支和上个发布分支的差异提交(方便测试同学针对性测试);
这么一通操作下来,大半天都过去了。如果能有个按钮,按一下自动帮助我们完成这些步骤就好了,我想到了使用流水线的方式来实现。
2. 实现步骤
目前我们的项目都是使用 gitlab 进行托管的,所以一键版本发布的功能也是基于 gitlab 流水线来实现的。
最终,我们实现了能够一键触发版本发布,先来看看最终的实现效果:
如下所示为触发版本发布的 python 脚本,我们只需要输入对应的参数,就能够一键触发了。
传递的参数中,ref 表示分支名,variables[***] 会写入到 gitlab 的环境变量当中。
def trigerReleaseVersion(trigger, version_code, version_name, base_unity_branch, base_android_branch,
release_branch, pre_branch):
token = "***"
webhookUrl = "https://***/trigger/pipeline"
data = {
"token": token,
"ref": base_android_branch,
"variables[BUILD_TAG]": "releaseVersionBuild",
"variables[TRIGGER]": trigger,
"variables[VERSION_CODE]": version_code,
"variables[VERSION_NAME]": version_name,
"variables[BASE_UNITY_BRANCH]": base_unity_branch,
"variables[RELEASE_BRANCH]": release_branch,
"variables[PRE_BRANCH]": pre_branch
}
response = requests.post(webhookUrl, data=data)
print(response.status_code)
return response.status_code
当然也可以通过一些网络接口工具去触发
3.1 前置条件
我们在工程的 yml 文件当中增加一个专门用于版本发布的任务,并设置只有当环境变量 BUILD_TAG 的值为 releaseVersionBuild 时才会被触发,触发之后会执行我们的 python 脚本。
releaseVersionBuild:
stage: build
rules:
- if: '$BUILD_TAG == "releaseVersionBuild"'
when: always
allow_failure: true
script:
- python3 main.py "releaseVersion"
tags:
- unity-ci
3.2 更新版本号和拉出发布分支
这一步相对来说比较容易,对于 Android 工程来说,我们需要修改版本号,提交变更,拉出发布分支,这几个功能都可以使用 python 的 git 库来实现。
1.clone 仓库并切换到指定的分支:
repo = git.Repo.clone_from(repo_url, directory)
repo.git.checkout(base_android_branch)
2.更改版本号,并提交代码:
with open(f'{directory}/gradle.properties', 'r') as file:
content = file.read()
origin = content
content = re.sub(r'VERSION_CODE=\d+', f'VERSION_CODE={version_code}', content)
content = re.sub(r'VERSION_NAME=.+', f'VERSION_NAME={version_name}', content)
if(origin == content):
print("not change")
print("不需要push新版本")
else:
print("changed")
with open(f'{directory}/gradle.properties', 'w') as file:
file.write(content)
repo.index.add(['gradle.properties'])
repo.index.commit(f'更新版本号到{version_name}')
repo.git.push('origin', base_android_branch)
print("版本push成功")
3.拉出发布分支,并 push 到远端
repo.git.checkout('-b', release_branch, base_android_branch)
repo.git.push('origin', release_branch)
而对于 Unity 工程来说,我们并不需要修改版本号,所以可以直接使用 gitlab 的接口,触发创建发布分支
def createBranch(project_id, baseBranch, newBranch, privateToken):
url = f"https://gitlab.***/api/v4/projects/{project_id}/repository/branches?branch={newBranch}&ref={baseBranch}"
headers = {
"PRIVATE-TOKEN": privateToken
}
response = requests.post(url, headers=headers)
if response.status_code == 201:
data = response.json()
return (True,"")
else:
print(f"Error: {response.status_code}")
print(response.json())
return (False,response.text)
3.3 生成 diffCommit
获取两个分支之间的差异,虽然可以使用 git 指令,但如果本地操作,再将其保存为文档给到测试同学,而且每次更新都需要重新生成再给一份,想想都觉得麻烦。
所以我创建了一个飞书多维表格,专门用于记录不同分支之间的差异提交记录,而且 gitlab 接口也支持获取分支之间的差异提交,这样每次编译的时候,都获取一下差异提交,再更新到多维表格当中就可以了。
获取不同分支之间的差异提交:
def getCommitDiff(project_id, fromBranch, toBranch, private_token):
url = f"https://gitlab.***/api/v4/projects/{project_id}/repository/compare"
headers = {
"PRIVATE-TOKEN": private_token
}
params = {
"from": fromBranch,
"to": toBranch
}
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
data = response.json()
commits = data['commits']
return commits
else:
print(f"Error: {response.status_code}")
print(response.json())
return None
更新多维表格的记录可以参考飞书开放平台的文档:
https://open.feishu.cn/document/server-docs/docs/bitable-v1/notification
还有一个问题需要解决,就是当我们发版的时候指定了 preBranch ,也就是和当前分支的对比的发布分支。
本来是想着可以通过程序来计算前一个发布分支,比如当前的发布分支是 release/1.2,那么前一个发布分支就是 release/1.1,但是实际发现有的时候会有一些临时版本,例如 release/1.1.5 或者 release/1.1_temp 之类的特殊版本,所以还是需要人工手动指定。
人工指定完了之后,还需要有个地方记录,这样每次有了新的提交,都需要去获取前一个分支,然后重新进行对比。同样可以记录在多维表格当中。
3.4 自动触发联动编译
我们可以在 yml 文件里面创建一个任务,只要有任何变更就触发,这样代码提交的时候就会触发执行我们的 python 脚本,我们可以在脚本里面判断当前的分支,如果分支名是 release/*** ,那么就可以开始版本发布的编译流程。
defaultTask:
stage: build
rules:
- changes:
- '*'
when: always
resource_group: $CI_COMMIT_REF_NAME
allow_failure: true
script:
- C:\\Application\\Python\\python.exe main.py "unityCompiler" #触发unity编译
after_script:
- C:\\Application\\Python\\python.exe main.py "triggerAndroid" #触发Android编译
tags:
- hmi3d-ci-windows
当 unity 编译完成之后,拿到了 aar 的版本号,此时可以触发 Android 流水线进行编译,并将aar 的版本号当作参数传递。其中 Android 发布分支和 unity 的发布分支的分支名是一样的。
def trigerAndroidProject(unityBranch, androidBranch, jobType, version, tag, user):
token = "***"
webhookUrl = "https://gitlab.***/trigger/pipeline"
data = {
"token": token,
"ref": androidBranch,
"variables[JOB_TYPE]": jobType,
"variables[VERSION]": version, # aar的版本号
"variables[BUILD_TAG]": tag,
"variables[TRIGGER]": user,
"variables[UNITY_COMMIT_MSG]": Utils.getLastCommitInfo(),
"variables[UNITY_BRANCH]": unityBranch,
"variables[ANDROID_BRANCH]": androidBranch,
"variables[BUILD_TIME]": Utils.getCurrentDateTime()
}
response = requests.post(webhookUrl, data=data)
print(response.status_code)
return response.status_code
这样就能够实现代码提交之后,自动触发 Unity 和 Android 两个工程联动编译。
3.5 让通知更友好
当编译完成之后,可以让飞书机器人发送消息进行提醒,这样就可以避免需要主动去流水线上查看是否编译结束,而且飞书机器人当中也可以携带各种参数,显示当前的编译信息。
3. 总结
这样我们就可以实现版本一键发布,并让通知更加友好,包打出来之后,测试同学可以直接在群里面看到消息,并开始测试,不需要互相通知。