跳到主要内容

使用Github Action自动部署网站/后端应用

随着写的项目越来越多,部署的需求也越来越多。

之前更新部署的方法是,写一个Bash脚本来半自动更新项目:

每当项目有新的改动完成时,对于前端项目是自动运行build script,然后通过scp工具上传到远程服务器(已经配置好Nginx设置),对于后端项目则是自动容器化应用,然后我依然需要ssh到服务器后台手动运行docker-compose.yml文件拉取并运行新的镜像。

总之,每次新的改动push到GitHub仓库以后,我均需要手动运行这个Bash脚本,终于到最近,我决定将这个过程全自动化!

因为最近一直在使用Vercel部署ChatGPT-Next-Web作为我的AI聊天助手,我发现每次有新的commit提交到这个仓库,我的Vercel应用就会自动更新,借此机会,我了解到了Github Action。

经过一番探索加试错,我终于成功将我的所有项目设置Github Action全自动化部署。

在此,我将记录一个典型的Workflow设置,以便之后参考:

name: CI/CD Pipeline

on:
  push:
    branches:
      - main

jobs:
  check-skip-ci:
    runs-on: ubuntu-latest
    outputs:
      skip: ${{ steps.check.outputs.skip }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Check for [skip ci] in commit message
        id: check
        run: |
          if [[ "${{ github.event.head_commit.message }}" == *"[skip ci]"* ]]; then
            echo "::set-output name=skip::true"
          else
            echo "::set-output name=skip::false"
          fi          

  build-and-deploy:
    needs: check-skip-ci
    if: needs.check-skip-ci.outputs.skip == 'false'
    runs-on: ubuntu-latest

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

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "20.12.2"

      - name: Install TypeScript
        run: npm install -g typescript@4.9.3

      - name: Install pnpm
        run: npm install -g pnpm

      - name: Install dependencies
        run: pnpm install

      - name: Build the project
        run: pnpm run build

      - name: Log in to DockerHub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./Dockerfile
          tags: ${{ secrets.DOCKER_USERNAME }}/bookkeeper:latest
          push: true

      - name: Deploy to remote server
        env:
          HOST: ${{ secrets.REMOTE_HOST }}
          USER: ${{ secrets.REMOTE_USER }}
          SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
        run: |
          echo "$SSH_PRIVATE_KEY" > private_key
          chmod 600 private_key
          ssh -i private_key -o StrictHostKeyChecking=no $USER@$HOST 'docker compose -f /root/www/bkp/docker-compose.yml down || true && sudo rm -f /root/www/bkp/docker-compose.yml'
          scp -i private_key -o StrictHostKeyChecking=no docker-compose.yml $USER@$HOST:/root/www/bkp/docker-compose.yml
          ssh -i private_key -o StrictHostKeyChecking=no $USER@$HOST <<EOF
            docker compose -f /root/www/bkp/docker-compose.yml pull
            docker compose -f /root/www/bkp/docker-compose.yml up -d
            docker system prune -f
          EOF
          rm -rf private_key          

在这个设置文件中,我添加了两个job,一个为check-skip-ci,另一个为build-and-deploy

check-skip-ci的作用是,当有新的commit被push到Github仓库中时,检查commit消息中是否含有[skip ci]字样,如果有,则跳过build-and-deploy,写这个job的目的是,例如有时可能我仅仅对README.md文件进行改动,此时我将不会希望我的项目会被重新build和部署,那么我可以在commit消息开头加上[skip ci]来跳过这一流程。

最后,环境变量的添加方法和位置如图所示。