# 使用 GitHub Actions 自动化部署你的项目

# 前言

最近写完了一个项目的后端部分,所以要部署到服务器上给前端调用接口,然后又因为前端调用接口的时候时不时出现一些问题就需要改代码,每次改完代码又需要重新部署项目到服务器,属实麻烦,于是我们的诺天大佬就利用 GitHub Actions 实现自动化部署。我也趁这个机会学习了一波把这个东西用到自己的项目上。

不过这东西还真是香啊,被微软收购的 Github 真是财大气粗。

# 组成

GitHub Actions 由四个部分组成:

  • workflow (工作流程):持续集成一次运行的过程,就是一个 workflow。
  • job (任务):一个 workflow 由一个或多个 jobs 构成,含义是一次持续集成的运行,可以完成多个任务。
  • step(步骤):每个 job 由多个 step 构成,一步步完成。
  • action (动作):每个 step 可以依次执行一个或多个命令(action)。

我觉得官方文档说这些东西说得绝对比我好:了解 GitHub Actions - GitHub Docs。所以我这里不在赘述。懒得写。

我这里还是主要说一下利用 Github Actions 实现自动化部署我的一个 SpringBoot Docker 项目到我的服务器上。多靠了诺天的帮助❤️(福瑞噢)。

# 编写 workflow 文件

# 用 Maven 打包 Java 项目

在我们需要实现自动化部署的项目仓库找到 Actions 然后创建一个 workflow 文件。

image-20220823153838564

我们点进去会发现有很多现成的轮子,我们可以从里面拿几个来用:

# 命名
name: Java CI with Maven
# 触发器
on:
# 触发事件
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]
jobs:
  build:
	# 将作业配置为在最新版本的 Ubuntu Linux 运行器上运行。
    runs-on: ubuntu-latest
    steps:
    # 运行 actions/checkout 操作的 v3
    - uses: actions/checkout@v3
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
      	# 选择 Java 版本
        java-version: '11'
        distribution: 'temurin'
        # 缓存 maven 依赖项
        cache: 'maven'
    - name: Build with Maven
      # 运行命令
      run: mvn -B package --file pom.xml

关于缓存 maven 依赖项,我发现 Github Actions 主页的 Java with Maven 中的 cache: maven 是没有单引号的,这样好像缓存不了依赖项。我看官方文档给的示例上是有单引号。actions/setup-java: Set up your GitHub Actions workflow with a specific version of Java

以上命令就是使用 Maven 打包你的 Java 项目。触发器在官方文档有更详细的解释:触发工作流程 - GitHub Docs

# 上传 jar 包到服务器

我们的项目是在我们服务器上运行的话,那就需要远程连接我们的服务器将打包好的 jar 包上传到我们服务器上面。

我使用的是这个仓库:easingthemes/ssh-deploy: GitHub Action for deploying code via rsync over ssh. (with NodeJS)

- name: Upload to server
        uses: easingthemes/ssh-deploy@v2.2.11
        env:
          ARGS: '-avz --delete'
          SOURCE: 'target/example.jar'
          TARGET: '/home/username/example'
          REMOTE_HOST: $<!--swig0-->
          REMOTE_USER: username
          SSH_PRIVATE_KEY: $

关于环境变量 env 在仓库中的 README 文件也说得很清楚了。 ARGS 参数,我们这里使用 -avzr --delete 参数,这个是 rsync 需要的参数( rsync 用来同步文件的,我们这里传 jar 包) 。 SOURCE 就是我们的 jar 包位置, TARGETjar 包存放到我们服务器里的位置, REMOTE_HOST 则是我们服务器的 ip, REMOTE_USER 我们登录服务器需要的用户名, SSH_PRIVATE_KEY 登录所需的私钥。私钥创建看我之前的文章(小声 bb)Linux SSH 远程配置及登录 - Linux | xun = 不失去热情 = 碎碎念 (asuka-xun.cc),你看我链接都摆这了🥺。

这里的 secrets.SERVER_ACCESS_KEYsecrets.SERVER_HOST 及后面的这些东西是需要我们在仓库中点击 Settings > Secrets > Actions > New repository secret。如下图:

image-20220823175349566

# 重启 docker 容器

可能有点疑惑为什么直接就到重启 docker 容器了,我当时也是疑惑不过我是先跑一边 git action 给我报错了说不存在这个容器(因为我当时是照着诺天大佬模板写的)。看到报错,很快啊,直接打开诺天的聊天窗截图发送,他也马上给了我回复。

我们第一次需要手动创建容器。采用的是使用 Docker 挂载文件功能将主机中的 jar 包挂载到容器内部,在容器内部执行 java -jar 命令,创建容器:

sudo docker run -d -p 8081:8080 -v /var/www/example/example.jar:/example.jar -v /var/www/example/config/application-prod.yml:/config/application-prod.yml --name ExampleContainer eclipse-temurin:17-jre java -jar /example.jar --spring.profiles.active=prod

注意前面是宿主机的绝对路径目录,后面是容器内目录,别搞反了。

刚刚我才发现诺天博客写了篇 Github Actions 的文章有说使用构建镜像的方法:Github Actions 实现项目自动部署 – 诺天的小世界 (furry.pro)

我们采用这个仓库的提供的方法 appleboy/ssh-action: GitHub Actions for executing remote ssh commands. 连接上我们的服务器并执行 docker 命令(注意这个方法只能执行 docker 命令。还有此处的 secrets.SERVER_ACCESS_KEY 这些跟前面一致):

- name: Restart Docker
        uses: appleboy/ssh-action@v0.1.4
        with:
          key: $<!--swig2-->
          host: $
          username: username
          script_stop: true
          script: |
            sudo docker restart Container

到此,我们的 workflow 文件基本就写完了。

# 完整示例

我的配置(SpringBoot Docker 项目)如下:

name: CI
on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@main
      - uses: actions/checkout@v3
      - name: Set up JDK 11
        uses: actions/setup-java@v3
        with:
          java-version: '11'
          distribution: 'temurin'
          cache: 'maven'
      
      - name: Build with Maven
        run: mvn -B package --file pom.xml
	
	 # 重命名 jar 包 
      - name: Rename target
        run: |
          mv target/*.jar target/example.jar
          
      # 将 jar 包上传到服务器
      - name: Upload to server
        uses: easingthemes/ssh-deploy@v2.2.11
        env:
          ARGS: '-avz --delete'
          SOURCE: 'target/example.jar'
          TARGET: '/home/username/example'
          REMOTE_HOST: $<!--swig4-->
          REMOTE_USER: username
          SSH_PRIVATE_KEY: $
      
      - name: Restart Docker
        uses: appleboy/ssh-action@v0.1.4
        with:
          key: $<!--swig6-->
          host: $
          username: username
          script_stop: true
          script: |
            sudo docker restart Container

注意:这里将 jar 包重命名了,方便使用。

创建容器 (docker 的命令这里不多解释):

sudo docker run -d -p 8081:8080 -v /var/www/example/example.jar:/example.jar -v /var/www/example/config/application-prod.yml:/config/application-prod.yml --name ExampleContainer eclipse-temurin:17-jre java -jar /example.jar --spring.profiles.active=prod

当然,Github Actions 能做的肯定不止这些,还需要自己发掘。也可以利用它自动化部署博客。

参考文章及文档:

Github Actions 实现项目自动部署 – 诺天的小世界 (furry.pro)

GitHub Actions 文档 - GitHub Docs