跳转到主内容
Avatar
GrapeWell

利用github actions实现自动化部署

2025-03-07

背景 #

在实现前后端部署之后,后续部署如果每次都手动的将文件传到服务器上面,例如在传统的开发场景中,我们需要手动打包,之后将打包的产物交给运维人员,运维人员在服务器上替换文件,这样效率不够高,并且负责的项目多了之后,可能会造成混乱。

这时候,需要使用一些自动化的流程,去帮助我们实现打包和部署的自动化,这里我用到了 github actions,它免费,流程较为简单,可以作为自动化部署的入门级流程,并且有很多三方工具可以使用,避免造轮子。

前端(React)的自动化部署 #

其他简单实现方式(手动) #

  • 利用 sftp 或 ftp 工具上传文件到服务器的指定目录
  • 利用 node 脚本编写上传命令在代码上传后执行

以 node 脚本为例

  1. 在 package.json 的 scripts 中增加文件上传
"upload": "scp dist xxx@xxx:/var/www/html"
  1. 执行命令
npm run upload

github actions #

  1. 在 github 仓库中选择 actions 创建自己的 actions
githubactions
  1. 书写自己的 actions,字段解释以及教程可参考阮一峰的教程 🔗
name: CI/CD

on:
  push:
    branches:
      - main # 只在master上push触发部署

jobs:
  build:
    runs-on: ubuntu-latest # 在虚拟机中执行任务
    steps:
      - name: Checkout # 拉取代码
        uses: actions/checkout@v3
      - name: Set Node.js 18.x # 指定nodejs版本
        uses: actions/setup-node@v3
        with:
          node-version: "18.x"
      - name: Install dependencies # 下载依赖
        uses: borales/actions-yarn@v4 # 使用yarn才加这个一般直接npm install
        with:
          cmd: install
      - name: Build #开始打包
        uses: borales/actions-yarn@v4 # 使用yarn才加这个一般直接npm build
        with:
          cmd: build
      - name: Deploy to Server
        uses: burnett01/[email protected] # 这里是第三方库,用于连接服务器并执行文件同步操作
        with:
          switches: -avzr --delete
          path: dist/
          remote_path: /home/frontend/weather-search
          remote_host: ${{ secrets.SSH_HOST }}
          remote_user: ${{ secrets.SSH_USERNAME }}
          remote_key: ${{ secrets.SSH_PRIVATE_KEY }}
  1. 添加 secrets 变量

    可以看到在上面的脚本中,使用了 secrets 变量,避免了在脚本中出现明文导致安全问题,尤其是直接出现 ssh 的私钥

    secrets
  2. 触发 github actions 检查是否能成功执行

    workflow

后端(koa)自动化部署 #

和前端比较类似,action 部分都差不多,也可以使用简单方式进行,需要注意的是,对没有必要放在服务器上的文件进行过滤

name: deploy-server

on:
  push:
    branches: main

jobs:
  deploy-server:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Set Node.js 18.x
        uses: actions/setup-node@v3
        with:
          node-version: "18.x"
      - name: Install dependencies
        run: npm install
      - name: Deploy to Server
        uses: burnett01/[email protected]
        with:
          switches: -avzr --delete
          path: /
          remote_path: /home/ubuntu/project/backend/weather-search-server
          remote_host: ${{ secrets.SSH_HOST }}
          remote_user: ${{ secrets.SSH_USERNAME }}
          remote_key: ${{ secrets.SSH_PRIVATE_KEY }}
          EXCLUDE: ".git, .gitignore" # 伪码,ssh deploy那个插件才有这个参数

唯一的区别在于前端项目使用了 nginx 反向代理,当前端文件变更时,nginx 加载的文件就是最新的文件,而后端是通过管理进程启动的服务,文件更新后,需要手动重启一次服务

实现自动重启服务 #

以 pm2 为例

  1. 在服务器的项目目录中增加ecosystem.config.js
module.exports = {
  apps: [
    {
      name: "server", // app name
      script: "./app.js", // 启动执行文件
      cwd: "/home/project/backend/", // script 执行目录
      watch: [
        // 监听文件路径
        "app.js",
        "config",
        "controller",
        "utils",
        "models",
        "router",
        "views",
      ],
      watch_delay: 1000, // 文件变化后,延迟重启时间
      ignore_watch: ["node_modules"], // 监听忽略路径
    },
  ],
};
  1. 执行pm2 start ecosystem.config.js

之后每次更新文件都会自动重启服务了

踩坑 #

  1. actions 里面的三方工具尽量用最新版本

  2. 执行到 deploy 时

    • permission denied 显示未登录

      解决办法:增加 -avzr —delete 参数

    • permission denied 显示没有权限操作

      解决办法:查看服务器上面放置文件的文件夹的权限,一般像/var/www/html 是 root 创建的,当前用户没有写的权限,建议将部署路径放置在/home 中,如/home/frontend/projectname