GitHub Actions驱动的SpringBoot项目构建

前尝试使用GitHub Actions进行过博客的自动部署发布,GitHub Actions集自动化构建、部署、发布于一体,仅需编写简短的YAML文件,便可实现持续集成发布,非常便捷高效,仅需在分支上进行一次push操作,就能够自动的发布到先上去。之前只是将静态的网页发布到GitHub Pages上,而本文尝试一些更为复杂的操作,即SpringBoot项目的持续集成构建部署发布。

Prerequisites

  • Git
  • GitHub
  • SSH
  • Java
  • 一台云服务器

Procedure

1. 创建一个SpringBoot项目

此部分不再赘述,可参考网上教程,通过Spring Initializr创建一个SpringBoot项目,并编写相关的Controller,本文使用的Controller如下所示:

1
2
3
4
5
6
7
@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
}

2. 创建一个GitHub仓库

在GitHub上创建一个新的仓库,并将本地的SpringBoot项目推送到GitHub上。

1
2
git remote add origin git@github.com:username/username.github.io.git
git push -u origin master

3. 配置GitHub Actions

GitHub Actions可以在本地进行创建,也可以在GitHub上进行创建,本文采用在GitHub上进行创建的方式,即在GitHub仓库的Actions选项卡下创建一个新的工作流,如下图所示:

Choose GitHub Actions◎ Choose GitHub Actions

此处我们选择Java with Maven作为基础的GitHub Actions模板,通过此模板,我们可以对SpringBoot项目进行构建,但是此模板并不支持将构建好的项目发布到云服务器上,因此我们需要对此模板进行一些修改,完整的Workflow如下所示:

 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
32
33
34
35
36
37
38
39
40
41
42
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven

name: Java CI with Maven

on:
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - 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
    - name: Scp to remote server
      uses: garygrossgarten/github-action-scp@release
      with:
        local: ./target/${{ secrets.JAR_NAME }}
        remote: /home/ubuntu/${{ secrets.JAR_NAME }}
        host: ${{ secrets.ECS_IP }}
        username: ${{ secrets.ECS_USERNAME }}
        password: ${{ secrets.ECS_PASSWORD }}
    - name: Deploy
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.ECS_IP }}
        username: ${{ secrets.ECS_USERNAME }}
        password: ${{ secrets.ECS_PASSWORD }}
        script: |
          nohup java -jar ${{ secrets.JAR_NAME }} &          

在原有的模板基础上加上了两个步骤,Scp to remote server以及Deploy步骤,分别用于将构建好的jar包发送到云服务器上以及运行jar包,Scp to remote server步骤使用了garygrossgarten/github-action-scp这个GitHub Action,而Deploy步骤使用了appleboy/ssh-action这个GitHub Action,这两个GitHub Action都是开源的,更多开源的GitHub Actions可以在编写GitHub Actions右侧的Marketplace中找到。

如你所见,在其中有很多不明的${{ secrets.XXX }},这些都是我们需要在GitHub仓库的Settings选项卡下的Secrets中进行配置的,如下图所示:

Set Secrets◎ Set Secrets

通过设置Secrets,我们可以将一些敏感信息隐藏起来,如上图所示,我们设置了三个Secrets,分别是ECS_IPECS_USERNAMEECS_PASSWORD,这三个Secrets分别对应云服务器的IP地址,用户名以及密码,而JAR_NAME则是我们构建好的jar包的名称。

4. 推送变更到GitHub

1
2
3
git add .
git commit -m "feat: add GitHub Actions"
git push

在GitHub打开对应的仓库,在Actions选项卡下可以查看到工作流的日志,等待其运行完成后,便可以在对应网页中看到结果。

Result◎ Result

Summary

创建GitHub Actions的过程并不复杂,但是通过这种方式进行持续集成开发会有一定缺陷。

  1. 在Workflow中,我们是通过SCP将构建好的jar包发送到云服务器上,由于GitHub的服务器大多在美国,而我们所选择的云服务器一般在中国,使用SCP传送数据往往会非常慢,以本文为例,构建出的jar文件约16MB,SCP命令执行时间约为10分钟,这样的时间还是非常漫长的,而实际生产过程中我们的jar包将会更大,那么这个时间就会更长,这样就会影响到我们的开发效率。后续将考虑使用GitHub Packages或者Docker进行优化。
  2. 在最后的构建过程中,为了使得jar包在后台运行,我们使用了nohup java -jar ${{ secrets.JAR_NAME }} &命令。但是问题就显而易见,除非运行jar包有误,否则GitHub Actions的Workflow将一直卡在这条指令,直至Workflow耗费完所有时间,这是显然有误的,这个问题应该也可以通过使用Docker解决。