使用GitHub Actions实现前端自动化打包、部署

一、前言

作为一名前端菜鸡,服务器小白,刚开始在Linux服务器上部署网站时,前端代码我一般都是打包后手动FTP传上去,后端代码直接在vscode中使用SSH连接服务器,直接同步代码更改。

但小黑作为一个生命不息折腾不止的程序猿,肯定要探索更好玩更高效的方法,所以这次,咱就上手折腾了下自动化部署方案

二、准备工作

1、持续集成服务(CI)方案选择

实现代码提交的自动化工作流,要依靠持续集成(CI)(或者加上持续交付(CD))服务。现在主流的公用免费的持续集成服务有:

  • Travis CI
  • Jenkins
  • Circle CI
  • Azure Pipeline
  • GitHub Actions

其中GitHub Actions是GitHub自家的持续集成及自动化工作流服务,简单易用,也是小黑本次使用的服务。它使用起来非常简单,只要在你的仓库根目录建立.github/workflows文件夹,将你的工作流配置(YAML文件)放到这个目录下,就能启用GitHub Actions服务。

小黑的网站是部署到腾讯云服务器上的,所以配置过程中用到了服务器相关配置,如果是想把网站放到GitHub Pages上,那只需要有个Github仓库就可以开始折腾起来了,下文关于远程服务器的配置可以忽略掉。

2、添加部署秘钥

要把文件部署到远程服务器,首先要解决登录校验的问题。
比较常见的就是密码登录、SSH密钥登录或者VNC登录。小黑推荐使用SSH密钥登录,既方便有安全。

2.1、生成SSH密钥对

相信需要远程部署到服务器的小伙伴肯定早就把SSH密钥对配置好了,所以我们可以直接对应的私钥文件内容复制一下,等下在GitHub中进行配置就可以啦!这里小黑就不再赘述啦

2.2、GitHub填写自动化配置项

SSH密钥对生成后,其实准备工作就已经完成的差不多了,最后一步就是将YAML文件中所需要的配置项,配置到Github上
首先打开对应的仓库,点击Setting > Secrets > New sceret,然后将我们复制的密钥文件内容、服务器host和登录用户名都添加到配置如下图对应的配置中,这样的话即使像小黑一样把项目开源,隐私信息也不会泄露啦。

20200927-161538-0487.png

配置完上面这些,我们的准备工作就大功告成了,接下来就可以编写工作流文件啦

三、配置过程

1、编写工作流文件

在仓库根目录中创建.github/workflows文件夹,再创建一个YAML文件,文件名自定,我这里起名叫deploy.yml,所以文件的完整路径应该为.github/workflows/deploy.yml,配置的意义写在注释中啦,当然小黑也会简略的介绍下重点配置项

1.1、文件基础配置

首先就是YAML文件比较基础的配置

on里的内容比较重要,指定自动触发工作流文件的事件,也可以将工作流设置为只在某些分支、路径或标记上运行。比如小黑就是在当master分支上进行push时才会触发,然后忽略掉README.mdLICENSE文件的变更

jobs里就是接下来所要运行的所有工作流程,小黑就设置了build-production这一个job,根据需要也可以设置多个

还有就是runs-on,小黑第一次还以为是要填写自己云服务器的操作系统,就填了个centos,一跑就报错,后来看了文档才明白,这是配置用来运行job的GitHub托管的新虚拟机,和你所使用的操作系统及服务器系统无关,和小黑一样配置为ubuntu-latest就行

strategy中的node-version可以不配置,为了和本地node版本统一,小黑配置了一下

steps里就是所需要运行的每一个具体的步骤啦,下面就让小黑一一道来

name: Blog CI/CD

on:
  push:
    branches:
      - master  # 只在master上push触发部署
    paths-ignore:   # 下列文件的变更不触发部署,可以自行添加
      - README.md
      - LICENSE

jobs:
  build-production:

    runs-on: ubuntu-latest   # 使用ubuntu系统镜像运行自动化脚本(温馨提示:和你所使用的操作系统及服务器系统无关,我本地用的windows10,云服务器用的centos)
    strategy: (可选)
      matrix:
        node-version: [12.x] # 配置所需node版本
    steps:  # 自动化步骤
    ……

1.2、下载代码

这一步就是检出你的仓库并下载里面的代码到runner中,actions/checkout@v2是官方自己造的轮子,直接拿来用就行

    - uses: actions/checkout@v2   # 第一步,检出仓库副本

1.3、配置node版本(可选)

这一步就是安装node,轮子也是官方的,版本可以选填,使用npm进行打包(不需要打包的项目可以省略1.3——1.5了)

    - name: Use Node.js ${{ matrix.node-version }} 
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }} #规定node.js版本(可不配置)

1.4、安装依赖

这一步就不用解释了吧

    - name: Install dependencies  # 第二步,安装依赖
      run: npm install

1.5、打包代码

这里小黑用了--if-present标志来避免脚本未定义时出现非零退出的情况,亲测在目前项目中写不写都行,不必纠结

    - name: Build              # 第三步,打包代码
      run: npm run build --if-present

在部署服务器时小黑踩到了很大的坑,就是明明打包完成了,但就是不结束任务,进入下一步

20200927-175017-0477.png

都带薪如厕回来了竟然还没有完成Build任务,这样小黑都没有烦躁也是多亏了和产品相爱相杀的磨练

换成yarn打包?失败+1
修改node版本?失败+2
……???????失败+N

是可忍叔不可忍,叔可忍他婶子也不可忍了!
这是要逼小黑使出大杀招了!
面对疾风吧!

…%…¥@*(¥@(*)
看我一顿操作猛如虎~

最后,在祭出三根宝贵的头发之后,终于让小黑找到了问题所在

我变秃了,也变强了! ——— 小黑

特么的竟然是打包后Node.js进程没有终止,平时直接手动Ctrl + C就顺便关了,根本没注意到这个问题!

暴风哭泣~

20200927-171341-0496.png

这时问题又来了,作为国服最菜前端,这webpack咱也只会个皮毛,观察模式也并没有开启呀,百度谷歌一顿搜,文档咱也看了又看,分析来分析去,也不晓得是哪个在占用Node.js进程,索性快刀斩乱麻,一行process.exit(0);直接乱杀!

20200927-171341-0497.png

push一下试试,果然Build任务成功完成,我特么真是个天才,奖励自己美味饲料一斤!

1.6、推送部署到服务器

打包成功,接下来就是激动人心的部署到服务器环节了,我们这里依然使用别人造好的轮子

DEPLOY_KEYSERVER_IPUSERNAME就是我们刚开始在Github里配置好SSH私钥、主机名、登录名,这里就不再赘述

主要需要留意的就是FOLDER、和SERVER_DESTINATION,也就是我们的推送文件夹及目标文件夹,这里一定要将路径写正确。

源码地址:rsync-deploy

    - name: Deploy to Server  # 第四步,rsync推送文件
      uses: AEnterprise/rsync-deploy@v1.0  # 使用别人包装好的步骤镜像
      env:
        DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}   # 引用配置,SSH私钥
        ARGS: -avz --delete --exclude='*.pyc'   # rsync参数,排除.pyc文件
        SERVER_PORT: '22'  # SSH端口
        FOLDER: ./build/*  # 要推送的文件夹,路径相对于代码仓库的根目录
        SERVER_IP: ${{ secrets.SSH_HOST }}  # 引用配置,服务器的host名(IP或者域名domain.com)
        USERNAME: ${{ secrets.SSH_USERNAME }}  # 引用配置,服务器登录名
        SERVER_DESTINATION: /www/wwwroot/lmsworld.cn/   # 部署到目标文件夹

我这里是直接将build文件夹内文件替换到网站根目录的,会存在非同名文件无法替换的情况,本来打算先删除网站根目录文件夹再替换的,但考虑到会有打包失败或者部署失败的可能性,删除后网站会无法访问,遂暂时不用此方法,后续有时间再继续改进,写在此处还是希望大佬们多多指点迷津~

1.7、重启服务(视情况而定)

如果是仅仅是部署了前端代码的话,那有可能就不用重启服务了,如果要后端代码的话,就要重新启动服务了
可以在YAML配置文件里另加一个后端部署的job,使用need控制下工作流,然后就在script里依次写下服务器上运行的命令行即可,小黑是用node写的后台,仅供参考

    - name: Restart server   # 第五步,重启服务
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.SSH_HOST }}  # 下面三个配置与上一步类似
        username: ${{ secrets.SSH_USERNAME }}
        key: ${{ secrets.DEPLOY_KEY }}
        # 重启的脚本,根据自身情况做相应改动,一般要做的是migrate数据库以及重启服务器
        script: |
          cd /www/server/web-server/
          pm2 reload app.js

1.8、完整配置文件

贴一下完整的配置文件,根据自己的项目情况修改下配置就行,不能用的话可以给小黑留言

name: Blog CI/CD

on:
  push:
    branches:
      - master  # 只在master上push触发部署
    paths-ignore:   # 下列文件的变更不触发部署,可以自行添加
      - README.md
      - LICENSE

jobs:
  build-production:

    runs-on: ubuntu-latest   # 使用ubuntu系统镜像运行自动化脚本(温馨提示:和你所使用的操作系统及服务器系统无关,我本地用的windows10,云服务器用的centos)
    strategy:
      matrix:
        node-version: [12.x] # 配置所需node版本
    steps:  # 自动化步骤
    - uses: actions/checkout@v2   # 第一步,检出仓库副本

    - name: Use Node.js ${{ matrix.node-version }} #规定node.js版本(可不配置)
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}

    - name: Install dependencies  # 第二步,安装依赖
      run: npm install

    - name: Build                 # 第三步,打包代码
      run: npm run build --if-present

    - name: Deploy to Server      # 第四步,rsync推送文件
      uses: AEnterprise/rsync-deploy@v1.0  # 使用别人包装好的步骤镜像
      env:
        DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}   # 引用配置,SSH私钥
        ARGS: -avz --delete --exclude='*.pyc'   # rsync参数,排除.pyc文件
        SERVER_PORT: '22'  # SSH端口
        FOLDER: ./build/*  # 要推送的文件夹,路径相对于代码仓库的根目录
        SERVER_IP: ${{ secrets.SSH_HOST }}  # 引用配置,服务器的host名(IP或者域名domain.com)
        USERNAME: ${{ secrets.SSH_USERNAME }}  # 引用配置,服务器登录名
        SERVER_DESTINATION: /www/wwwroot/lmsworld.cn/   # 部署到目标文件夹

    # - name: Restart server   # 第五步,重启服务
    #   uses: appleboy/ssh-action@master
    #   with:
    #     host: ${{ secrets.SSH_HOST }}  # 下面三个配置与上一步类似
    #     username: ${{ secrets.SSH_USERNAME }}
    #     key: ${{ secrets.DEPLOY_KEY }}
    #     # 重启的脚本,根据自身情况做相应改动,一般要做的是migrate数据库以及重启服务器
    #     script: |
    #       cd /www/server/web-server/
    #       pm2 reload app.js

2、最终效果

小黑迫不及待的将配置文件修改后push到仓库,这次工作流跑的行云流水,啥错都没报,简直完美!

在这个面板里你可以看到具体每一步任务的耗时与输出信息,报错信息也可在这里查询哦

20200928-102853-0494.png

最后如果你是部署到腾讯云、阿里云等云服务平台的话,一般会收到一条安全警告通知,比如小黑用的就是腾讯云

20200928-114201-0477.png

存在来自ip:40.122.43.158的异常登录,这ip是谁的,让小黑查一下
20200928-110204-0490.png

Microsoft数据中心?应该就是github服务器的ip了,问题不大,这里就先不管他了,后续咱们再找方法解决它

四、待优化部分

小黑最近工作太忙,只是先简单实现了自动化部署功能,但是还没来得及进行优化,先留个坑,后续再更

1、缓存依赖加快工作流

GitHub文档-缓存的依赖关系

2、COS 优化部署

GitHub Actions + COS 优化部署

五、参考

由于小黑见识浅薄、水平有限,所写内容肯定有很多不足之处,还请各位大佬不吝赐教,十分感激!

以下文档、博客给了小黑极大的帮助,在此表示炒鸡感谢!

1、GitHub Actions文档
2、How to deploy a create-react-app with github-actions
3、使用 GitHub Actions 实现博客自动化部署

本篇文章由一文多发平台ArtiPub自动发布

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343