使用 GitHub Actions 自动部署 Node.js 服务端(宝塔面板)

26 年 3 月 1 日 星期日
729 字
4 分钟

最近因为个人需要就用 node 写了个小项目,想到现在基本上都用 node 来写服务端,于是写的时候就想要顺便试试用 GitHub Actions 来做自动部署,这样就不用写完还要我自己构建代码然后再打开宝塔面板上传文件再重启服务了

这个 action 的前提条件是使用宝塔面板,已经创建了项目并且正在运行中。等现在这个服务器到期迁移到新服务器之后我打算扔掉宝塔面板,到时候会研究新的 CI/CD,大概率是用 pm2 吧

设计思路

  • 从 package.json 中获取当前的版本
  • 通过接口获取线上运行的版本
  • 对比版本号,版本号一致则结束任务,不一致则开始进行构建
  • 构建代码,上传
  • 运行宝塔的重启脚本重启服务端

完整 Workflow

yaml
name: Node Service CI/CD

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Read package info
        id: pkg
        run: |
          NAME=$(jq -r .name package.json)
          VERSION=$(jq -r .version package.json)
          echo "name=$NAME" >> $GITHUB_OUTPUT
          echo "version=$VERSION" >> $GITHUB_OUTPUT

      - name: Fetch remote version
        id: remote
        run: |
          RESPONSE=$(curl -s --max-time 20 https://${{ secrets.API_URL }}/info || echo "fail")

          if [ "$RESPONSE" = "fail" ]; then
            REMOTE_V="none"
          else
            REMOTE_V=$(echo "$RESPONSE" | jq -r '.data.version // "none"')
          fi

          echo "version=$REMOTE_V" >> $GITHUB_OUTPUT

      - name: Compare version
        id: compare
        run: |
          LOCAL="${{ steps.pkg.outputs.version }}"
          REMOTE="${{ steps.remote.outputs.version }}"

          if [ "$LOCAL" = "$REMOTE" ]; then
            echo "skip=true" >> $GITHUB_OUTPUT
          else
            echo "skip=false" >> $GITHUB_OUTPUT
          fi

      - name: Setup Node
        if: steps.compare.outputs.skip == 'false'
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm

      - name: Install dependencies
        if: steps.compare.outputs.skip == 'false'
        run: npm ci

      - name: Build
        if: steps.compare.outputs.skip == 'false'
        run: npm run build

      - name: Prepare target directory
        if: steps.compare.outputs.skip == 'false'
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SERVER_IP }}
          username: github_upload
          key: ${{ secrets.SERVER_SSH_KEY }}
          script: |
            mkdir -p "/www/wwwroot/${{ steps.pkg.outputs.name }}"
            rm -rf "/www/wwwroot/${{ steps.pkg.outputs.name }}/*"

      - name: Upload dist
        if: steps.compare.outputs.skip == 'false'
        uses: appleboy/scp-action@v0.1.7
        with:
          host: ${{ secrets.SERVER_IP }}
          username: github_upload
          key: ${{ secrets.SERVER_SSH_KEY }}
          source: 'dist/*'
          target: '/www/wwwroot/${{ steps.pkg.outputs.name }}'
          strip_components: 1

      - name: Restart service
        if: steps.compare.outputs.skip == 'false'
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.SERVER_IP }}
          username: ${{ secrets.SERVER_USERNAME }}
          key: ${{ secrets.SERVER_SSH_KEY }}
          script: |
            sudo /www/server/nodejs/vhost/scripts/deploy_restart.sh "${{ steps.pkg.outputs.name }}"

部分内容解释

  1. 构建与上传

    构建与上传时会使用 package.json 中的 name 来作为项目名,将构建完成的文件上传到相应的路径中,重启服务时使用的也是这个项目名,需要注意

  2. Workflow 需要的 secret 列表

    secret说明示例
    API_URL线上服务的 API 地址,不需要协议api.chiyukiruon.com
    SERVER_IP服务器地址-
    SERVER_USERNAME服务器登录用户名-
    SERVER_SSH_KEY服务器登录私钥-
  3. 版本检查接口

    对应的服务需要实现 /info 接口来实现版本检查功能,接口返回值示例:

    json
    {
      "code": 200,
      "message": "Service is ready",
      "data": {
        "service": "API Service",
        "version": "1.6.2",
        "environment": "production"
      }
    }
  4. 重启服务

    重启服务使用的是宝塔面板的重启脚本,只有使用这个脚本重启才能让宝塔面板识别到项目已经启动,默认情况下这个脚本的路径是 /www/server/nodejs/vhost/scripts/deploy_restart.sh,只要后面再加上项目名称就可以重启对应项目了

文章标题:使用 GitHub Actions 自动部署 Node.js 服务端(宝塔面板)

文章作者:千雪琉音

文章链接:https://chiyukiruon.com/posts/bt-node-cicd[复制]

最后修改时间:


ChiyukiRuon

商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。