Github Action以及其他持续集成方案

字数 5852 阅读 145 喜欢 0

GitHub Actions 是 GitHub 的持续集成服务,于2018年10月推出。
说到持续集成,就得提下前端工程化

前端部署发展史

前端一说起刀耕火种,那肯定紧随着前端工程化这一话题。随着 react/vue/angular,es6+,webpack,babel,typescript 以及 node 的发展,前端已经在逐渐替代过去 script 引 cdn 开发的方式了,掀起了工程化这一大浪潮。得益于工程化的发展与开源社区的良好生态,前端应用的可用性与效率得到了很大提高。

刀耕火种

本地开发完,根据项目 通过webpack或者rullup构建成静态文件,然后压缩扔给后台或者运维,运维将静态资源放在服务。可能中间运维还会向你要一份部署文档,大部分情况下是nginx的配置。

server {
  listen 80;
  server_name server.nam;

  location / {
    # 避免非root路径404
    try_files $uri $uri/ /index.html;
  }

  # 解决跨域
  location /api {
    proxy_pass http://api.server.nam;
  }

  # 为带 hash 值的文件配置永久缓存
  location ~* \.(?:css|js)$ {
      try_files $uri =404;
      expires 1y;
      add_header Cache-Control "public";
  }

  location ~ ^.+\..+$ {
      try_files $uri =404;
  }
}

这个时候,无论跨域的配置还是缓存的配置,都是运维来管理,运维不懂前端。但配置方式却是前端在提供,而前端并不熟悉 nginx

使用Docker构建

docker的引进,解决大部分部署问题。dockerfile就是部署脚本,部署脚本就是dockerfile。这种方式很大程度上缓解了前端与运维人员之间的摩擦,至少部署脚本没有问题了。。。

这时候,前端提供的不再是静态资源,而是提供了一个服务,一个http服务

FROM node:alpine

# 代表生产环境
ENV PROJECT_ENV production
# 许多 package 会根据此环境变量,做出不同的行为
# 另外,在 webpack 中打包也会根据此环境变量做出优化,但是 create-react-app 在打包时会写死该环境变量
ENV NODE_ENV production
WORKDIR /code
ADD . /code
RUN npm install && npm run build && npm install -g http-server
EXPOSE 80

CMD http-server ./public -p 80

有了dockerfile就意味着前端需要维护 docker-compose.yaml,然后运维人员执行docker-compose up -d

但是这种模式也会存在一些问题:

  1. 构建镜像体积过大。
  2. 构建时间太长。

当然这些问题都是可以优化的

FROM node:alpine as builder

ENV PROJECT_ENV production
ENV NODE_ENV production

WORKDIR /code

ADD package.json /code
RUN npm install --production

ADD . /code

# npm run uploadCdn 是把静态资源上传至 oss 上的脚本文件,将来会使用 cdn 对 oss 加速
RUN npm run build && npm run uploadCdn

# 选择更小体积的基础镜像
FROM nginx:alpine
COPY --from=builder code/public/index.html code/public/favicon.ico /usr/share/nginx/html/
COPY --from=builder code/public/static /usr/share/nginx/html/static
  1. 利用镜像缓存,减少构建时间。
  2. npm install --production
  3. npm cache 或者使用npm 私库

但是这里仍然会有些问题,比如缓存,比如跨域等问题。

CI/CD与gitlab

  • CI,Continuous Integration,持续集成
  • CD,Continuous Delivery,持续交付
    通过与仓库代码添加持续集成方案。工程负责人只需要编写工程的yml就可以了。
deploy:
  stage: deploy
  only:
    - master
  script:
    - docker-compose up --build -d
  tags:
    - shell

当然我们还可以在持续集成方案中添加各种linttestpackage等安全检测,提高代码质量。

kubernetes + jenkins

https://static.jinhaidi.cn/images/20200524171055.png?jhd_blog_image

Jenkins 拥有丰富的插件、良好的生态社区、开源、基于java可移植到所有的主要平台。
Jenkins能够与主流的源代码管理系统(Git、SVN、Mercurial以及CVS)、主流的构建工具(Ant、Maven、Grunt)、shell脚本和Windows批处理命令、测试框架、报表生成器的都良好地协同工作。
并且Jenkins有良好的可伸缩性:

  1. 并行运行多个构建方案
  2. 自动挂载和移除代理、节约开销
  3. 分配负载

GitHub Action

但是这种方案并不适合独立开发者,或者个人使用。虽然好用,但是太庞大,而且个人搭建浪费资源。毕竟能省就省才是王道。

所以这里就介绍到了今天的主题GitHub Action(下面简称action)
action其实是GitHub的持续集成服务。相信大家肯定也用过Travis CI。

Travis CI 提供的是持续集成服务(Continuous Integration,简称 CI)。它绑定 Github 上面的项目,只要有新的代码,就会自动抓取。然后,提供一个运行环境,执行测试,完成构建,还能部署到服务器。

大家知道,持续集成由很多操作组成,比如抓取代码、运行测试、登录远程服务器,发布到第三方服务等等。GitHub 把这些操作就称为 actions。

很多操作在不同项目里面是类似的,完全可以共享。GitHub 注意到了这一点,想出了一个很妙的点子,允许开发者把每个操作写成独立的脚本文件,存放到代码仓库,使得其他开发者可以引用。

如果你需要某个 action,不必自己写复杂的脚本,直接引用他人写好的 action 即可,整个持续集成过程,就变成了一个 actions 的组合。这就是 GitHub Actions 最特别的地方。

官方市场 ,在这里可以搜索到其他人提交的actions

基本概念

Github Action 分为四部分

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

workflow

GitHub Actions 的配置文件叫做 workflow文件 ( yaml格式 ),存放在代码仓库的.github/workflows目录。
具体配置大家可以去看 官方文档 ,我在这里就不一一赘述了 (懒
这里给大家贴一个我自己的 工程示例
https://static.jinhaidi.cn/images/20200524173756.png?jhd_blog_image
通过上图我们可以看到 我们每次的push commit 都会触发action,CI结束之后我们可以可以查看完整的日志。

我工程的主要诉求就是验证成功直接push到我阿里云的机器上面实现代码reload。这里我采用的是官网市场开源的一个action appleboy/ssh-action ,主要就是通过ssh登陆服务器,执行某个shell脚本 实现工程的reload。

nodejs.yml

# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: Node.js CI

on:
  push:
    branches: [ master ]
  pull_request:
    types: [closed]
    branches:
      - master

jobs:
  deploy:

    runs-on: ubuntu-latest
    name: Deploy to server
    steps:
      - name: Exec deploy script with SSH
        uses: appleboy/ssh-action@master
        with:
          command_timeout: 8m
          host: ${{ secrets.ALIYUM_HOST }}
          username: ${{ secrets.ALIYUM_USER }}
          password: ${{ secrets.ALIYUM_PWD }}
          port: ${{secrets.ALIYUM_PORT }}
          script: sh ${{ secrets.PATH }}/blog-front/.deploy/main.sh
这里secrets.ALIYUM_HOST这种变量可以在仓库的setting里面进行设置
https://static.jinhaidi.cn/images/20200524175428.png?jhd_blog_image

这里的 secret 就是一种 context,描述 CI/CD 一个 workflow 中的上下文信息,使用 ${{ expression }} 语法表示。

除了 secret,还有

  • github: workflow 的信息,如 github.sha 可以获取当前的 commit SHA,我们可以利用它为 sentry 或者 docker image 打入版本号
  • env: 环境变量
  • job: 当前执行 job 的信息,如 job.status 表示当前 job 的执行状态
  • matrix: 描述一些构建信息,如 node 以及 os 版本号

rebuild.shell

#!/bin/bash

WEB_PATH=$(dirname $0)
# WEB_USER='root'
# WEB_USERGROUP='root'

echo "[deploy] Fetch and rebuilding..."
cd $WEB_PATH
cd ..
echo "[deploy] path:" $(pwd)
echo "[deploy] pulling source code..."
git fetch --all && git reset --hard origin/master && git pull
git checkout master
echo "[deploy] building..."
npm ci
npm run build
echo "[deploy] Rebuild done."

以上就是今天要给大家分享的,没尝试过的小伙伴一定要去尝试下,真香!!!