利用 github 的 actions 为你的前端项目加上 CI(Continuous Integration,持续集成)

一、创建前端项目

这里以 angular 项目为例,其他框架同理

前端的三大框架(Angular、React 和 Vue)目前均有自己比较成熟的脚手架(cli)可用于项目从创建开发构建部署一系列的工作,从而使得前端部分的工作从开发到交付保持比较高的效率。

但仅仅如此还不够,因为在部署环节,其实不同开发者有这不同的“套路”,有使用 jenkins 的,也有在本地编译再通过 scp 传输到服务器的。但这些在 CI 面前都显得不够“自动化”。

我们稍微总结一下:

前端有三大框架

  • Angular
  • React
  • Vue

分别对应有自己的脚手架工具

  • @angular/cli
  • create-react-app
  • @vue/cli

前端项目从 0 到 1 到上线主要环节有

  • 创建
  • 开发
  • 构建
  • 部署

主流部署方式有

  • jenkins
  • scp

接下来进入今天的主要环节,如何利用 github 的 actions 功能实现项目 CI

二、github actions

按照 github actions 的指示操作后,会创建一个.github/workflows/blank.yml 文件

这个文件承载着整个 github actions 的配置,也就意味着当你在 github 某个仓库中包含.github/workflow/xxx.yml 文件后,你在操作这个仓库时就会触发对应的 action。比如我们如下配置可使得每次在对 smartshop 这个项目的 master 分支上进行 push 时触发如下动作:

  1. 在 github 所提供的某台云服务器 A 上安装 node 和 npm
  2. 在服务器 A 上安装@angular/cli
  3. 利用安装好的@angular/cli 对 smartshop 项目进行编译
  4. 将编译生成的目录通过 scp 发送到指定的服务器 B
# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
  push:
    branches: [master]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2
      # this installs node and npm for us
      - uses: actions/setup-node@v1
        with:
          node-version: "10.x"
      # this allows for re-using node_modules caching, making build a bit faster
      - uses: actions/cache@v1
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-            

      # Runs a single command using the runners shell
      - name: npm install
        run: npm install

      - name: install ng-cli
        run: npm install -g @angular/cli > /dev/null

      - name: build
        run: npm run build
        # run: ng build --prod

      - name: copy file via scp
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USERNAME }}
          port: ${{ secrets.PORT }}
          password: ${{ secrets.PASSWORD }}
          source: "./dist/znsc-ng"
          target: "/home/webapp/"

其中比较关键的也是开发者比较关心的是自己要部署的服务器信息,这部分内容当然是不会直接明文写在配置文件中的,所以在这里 github actions 利用了变量进行处理。而这个变量值的设置则是通过另一个地方进行保存

插曲一

初始化的阿里云 ECS 由于控制台配置,默认的 80 端口可能不是 nginx 服务器,也有可能被其他程序占用,可通过以下命令查看

netstat -anop | grep 0.0.0.0:80
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1905/java            off (0.00/0/0)
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      24066/httpd          off (0.00/0/0)
tcp        0      0 0.0.0.0:8009            0.0.0.0:*               LISTEN      1905/java            off (0.00/0/0)

可发现 80 端口被 apache 服务器的 httpd 进程所占用,如果使用 apache 服务器,可通过配置 apache 所占 80 端口默认访问的静态文件入口,操作如下:

whereis httpd
httpd: /etc/httpd /usr/local/apache/bin/httpd

cd /etc/httpd

vi httpd.conf

/80

/DocumentRoot

如果使用 nginx 服务器,可通过以下命令查找 nginx 服务器当前使用的配置文件

whereis nginx
nginx: /usr/local/nginx

cd /usr/local/nginx
cd sbin

./nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

插曲二

angular 项目中可能会使用到样式预处理器,当依赖 node-sass 包后可能会下载失败。此时可使用 node-sass 官网所提供的另一个包提供可供下载该包的源配置,如下

npm install -g mirror-config-china --registry=https://registry.npm.taobao.org

参考

结论

这样我们就可以愉快地在功能分支进行开发和提交,在 master 分支进行 push 到远程仓库,并自动触发部署动作,完成更新上线了。这样既省去了每次手动部署的操作,也无需对服务器私密信息进行本地保存,实属 github actions 为我们提供的一种 CI 最佳实践

参考资料