我自己实现了一个名为toolkit
的程序集,它被部署在私有VPS上,主要用于满足自己的需求。比如gitea的webhook邮件通知,我就是放在toolkit程序上实现的。
为了简化部署流程,我又引入了CD,在gitea上自动化构建、打包、上传docker镜像到私有registry、然后远程连接部署机器,拉取最新的镜像并重启服务以实现自动化更新部署。
这其中就产生了一个问题:toolkit是webhook的具体接收者,其他仓库构建失败时触发webhook不会出现任何问题,但是如果toolkit在部署过程中一旦出现意外——比如重启服务后由于某些配置导致程序无法正常启动——将无法处理webhook事件,也无法通过邮件通知到我。
因此,为了避免这样的情况,我需要专门针对toolkit的工作流进行特殊操作,以实现当进行的工作流出现问题时,可以将老版本的服务重新拉起来进行恢复,并在此基础上发送邮件通知。
核心要点在于刚通过ssh远程连接VPS时,就保存老版本关键信息到VPS的临时文件中,并在部署出错后通过读取临时文件中的配置重启旧版本的服务。
部署步骤 具体来说,部署步骤的实现是:
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 - name: Backup current image and deploy new version id: deploy uses: appleboy/ssh-action@v1 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} key: ${{ secrets.KEY }} port: 22 script: | set -e # 重要,对于新版本的ssh-action,远程执行出错时自动中止当前step并将状态设置为执行失败 CURRENT_IMAGE=$(docker inspect toolkit --format='{{.Config.Image}}' 2>/dev/null || echo "") # 获取容器`toolkit`的`Config.Image`字段,保存到变量中 echo "$CURRENT_IMAGE" > /tmp/toolkit_backup_image.txt # 将其保存到远程主机的临时文件中 # 确保停止并删除容器 docker stop toolkit || true docker rm toolkit || true # 登陆registry # 拉取镜像 # docker run 启动新的镜像 sleep 10 #等待10秒以确保程序进入正常运行的状态 if ! docker ps | grep -q toolkit; then echo "New container failed to start!" exit 1 fi rm /tmp/toolkit_backup_image.txt
错误恢复步骤 工作流的step支持条件执行,而failure()
条件表示此step的所在job之前的任意一个step执行失败时值为真,主要用于失败时的错误处理。所以我可以把错误处理放在一个新的step中进行处理,避免在部署步骤中进行错误处理,从而简化:
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 31 - name: Rollback on failure if: failure() uses: appleboy/ssh-action@v1 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} key: ${{ secrets.KEY }} port: 22 script: | # 读取临时文件中的配置到变量中 BACKUP_IMAGE=$(cat /tmp/toolkit_backup_image.txt 2>/dev/null || echo "") # 如果都读取不到就没办法了,直接停止运行 if [ -z "$BACKUP_IMAGE" ]; then echo "No backup image found, cannot rollback." exit 1 fi # 确保停止并删除容器 docker stop toolkit || true docker rm toolkit || true # 使用包含老版本的Image属性的临时变量来启动一个新的容器 docker run -d \ --name toolkit \ --restart always \ -v /etc/localtime:/etc/localtime:ro \ "$BACKUP_IMAGE" echo "Rollback completed. Notification service should be restored." echo "Rolling back to: $BACKUP_IMAGE" sleep 10 rm -f /tmp/toolkit_backup_image.txt
最终效果