Go项目-持续部署-阿里云服务器
tbghg

CI/CD 这块自己一直都是一知半解的,最近有个七牛云的比赛,持续部署做的比较敷衍,webhooks + hookdoo,目前赛后复盘,把这块恶补一下

基本概念

参考文章:持续集成、持续交付、持续部署 基本概念

  • CI 持续集成(Continuous Integration)
  • CD 持续交付(Continuous Delivery)
  • CD 持续部署(Continuous Deployment)

持续集成

image

持续集成强调开发人员提交了新代码之后,立刻进行构建、(单元)测试。根据测试结果,我们可以确定新代码和原有代码能否正确地集成在一起。

持续集成 (CI) 是一种需要频繁提交代码到共享仓库的软件实践。 频繁提交代码能较早检测到错误,减少在查找错误来源时开发者需要调试的代码量。 频繁的代码更新也更便于从软件开发团队的不同成员合并更改。 这对开发者非常有益,他们可以将更多时间用于编写代码,而减少在调试错误或解决合并冲突上所花的时间。

提交代码到仓库时,可以持续创建并测试代码,以确保提交未引入错误。 您的测试可以包括代码语法检查(检查样式格式)、安全性检查、代码覆盖率、功能测试及其他自定义检查。

持续交付

image

持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的「类生产环境」(production-like environments)中。

持续部署

image

持续部署则是在持续交付的基础上,把部署到生产环境的过程自动化。

总结一下:持续集成是构建测试代码并检测与源代码是否存在冲突,持续交付是交付给QA,持续部署是尽快部署生产

持续部署-实战练习

用最近做的七牛云1024比赛项目来练习吧,一个 Golang 后端项目,持续交付不需要做,持续集成参考 GitHub Action 的文档即可,在此简单看下持续部署

我们想把代码部署到阿里云服务器上,步骤如下:

  1. GitHub Action构建项目
  2. 将构建好的二进制文件传到阿里云服务器
  3. 服务器直接运行二进制文件

首先,在 GitHub secrets 中配置阿里云服务器登录信息

image

然后开始编写 workflow 配置文件,我们可以直接选用 GitHub Actions 中的模板

image

基础的语法参考 GitHub Actions 的文档,我们想要部署到自己的服务器,需要用到 easingthemes/ssh-deployappleboy/ssh-action,前者是将文件通过 scp 命令传入,后者是直接执行命令

# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go

name: Go

on:
  push:
    branches: [ "master" ]
# 持续部署时只跑主分支上的master,PR不用管
#  pull_request:
#    branches: [ "master" ]

jobs:

  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Set up Go
        uses: actions/setup-go@v4
        with:
          go-version: '1.21'

      - name: Build
        run: CGO_ENABLED=0 go build -o server

      - name: Sent to ALIYUN
        uses: easingthemes/ssh-deploy@main
        env:
          #私钥
          SSH_PRIVATE_KEY: ${{ secrets.ALIYUN_SERVER_PRIVATE_KEY }}
          #scp参数
          ARGS: "-rltgoDzvO --delete"
          #源目录
          SOURCE: "./server ./cmd/run.sh"
          #服务器IP
          REMOTE_HOST:  ${{ secrets.ALIYUN_SERVER_HOST }}
          #用户
          REMOTE_USER: ${{ secrets.ALIYUN_SERVER_REMOTE_USER }}
          #目标地址
          TARGET: "/root/utopia-back"

      - name: Deploy on ALIYUN
        uses: appleboy/ssh-action@master
        with:
          host:  ${{ secrets.ALIYUN_SERVER_HOST }}
          username: ${{ secrets.ALIYUN_SERVER_REMOTE_USER }}
          password: ${{ secrets.ALIYUN_SERVER_PWD }}
          debug: true
          script: |
            cd /root/utopia-back
            chmod +x ./run.sh
            ./run.sh

编译时尽量使用静态编译(CGO_ENABLED=0),保证服务器不用配置额外环境,可直接运行

scp 命令用到的参数如下:

  • -r: 递归复制整个目录结构,包括子目录和文件
  • -l: 保持源文件和目标文件的链接关系
  • -t: 在远程服务器上创建与源目录相同的目录结构
  • -g: 保持文件的原始属性,包括所有者、组和权限
  • -o: 保持源文件的时间戳
  • -D: 启用调试模式,在传输过程中显示调试信息
  • -z: 在传输过程中启用压缩,以减少数据传输的大小
  • -v: 显示详细的传输信息,包括每个文件的名称和传输进度
  • -O: 保持源文件的所有者和组
  • --delete: 删除远程目标目录中存在但源目录中不存在的文件

./cmd/run.sh内容如下:

#!/bin/bash

# 检查8080端口的占用情况
port=8080
pid=$(lsof -t -i:$port)

if [ -z "$pid" ]; then
  echo "端口 $port 没有被占用。"
else
  echo "端口 $port 被进程 $pid 占用。"

  # 终止占用8080端口的进程
  echo "终止进程 $pid ..."
  kill $pid

fi

echo "开始启动Go程序..."
nohup ./server > output.log 2>&1 &
sleep 2 # 等待一段时间以确保程序已经启动
pid=$!
if [ -n "$(ps -p $pid -o pid=)" ]; then
  echo "Go程序已成功启动。"
  exit 0
else
  echo "Go程序启动失败,请检查错误信息。"
  exit 1
fi

另外关于端口,可以在appleboy/ssh-action里指定,通过参数的形式写进run.sh

现在当我们提交后,观察Github Actions,发现流程正常通过,且程序正常部署

image

当然,上面实现的是比较繁琐的,直接用docker会好很多,以后有时间了补一下

Webhooks 实现

image

当然,我们也可以通过 Webhooks 来实现部署,简单来说当我们进行相应操作后,Github 会向我们配置的 url 发起 POST 请求,服务器上编写相应的接口,收到请求后进行相应处理即可。例如,先通过 Github Actions 将构建好的文件 scp 到自己的服务器上,收到 POST 请求后再进行对应的处理。

如果比较懒的话,可以去看下 hookdoo(Hooks to automate webhooks),这个使用较为简单,在此不多赘述

当然,也可以通过 Github Actions 触发 Webhooks,这样就不用去想二者先后顺序之类的了

可参考文章:GitHub Actions 和 Webhooks 的触发

 评论