Skip to content

Github Action 文档

如果还需要更多关于 github action 相关的知识, 可以看这里

笔记对应的代码

https://github.com/lh5sa/learn-github-actions-demo

部署项目到 Github Pages

为什么部署 vitepress 项目作为示例?

因为 vitepress 项目也需要编译, 部署 vitepress 步骤和部署 vue.js 项目是一样的, 但是 vitepress 的项目依赖比价少, npm install 的时候速度比较快点

为什么部署到 Github Pages ?

因为很多开源项目都是用这种方式部署的, 如果你想写个不错的开源产品, 在线文档是必不可少的, 那么 Github Pages 就是一个很好的选择

1. 新建 Github 仓库, 开启 Github Pages 功能

仓库名是很重要, 如: learn-github-actions-demo

2. 修改 vitepress 的配置

配置 vitepress 代码的 base 字段/learn-github-actions-demo/

js
export default {
  base: '/learn-github-actions-demo/',
};

3. 创建 Github Action 配置文件

在项目根目录下创建 .github/workflows/deploy.yml, 参考vitepress文档:

yml
# 工作流名称可以填写一些描述信息,这个配置文件是做什么用的
name: Deploy VitePress site to Pages

# 什么时候触发, 执行这个 Action
# 当代码提交到 main 分支的时候触发
on:
  push:
    branches: [main]

  # 允许手动在项目仓库主页的 Actions 中手动运行
  workflow_dispatch:

# 需要的权限有哪些
permissions:
  contents: read
  pages: write
  id-token: write

# 是否可以取消(如果 action 正在运行的时候)
concurrency:
  group: pages
  cancel-in-progress: false

jobs:
  #### 构建流程 ####
  build:
    runs-on: ubuntu-latest
    steps:
      # 下载仓库中的源代码
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0
      # - uses: pnpm/action-setup@v2 # Uncomment this if you're using pnpm
      # - uses: oven-sh/setup-bun@v1 # Uncomment this if you're using Bun

      # 安装 node 环境
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: npm # or pnpm / yarn

      # 配置 Github Pages
      - name: Setup Pages
        uses: actions/configure-pages@v3

      # 安装项目需要的依赖
      - name: Install dependencies
        run: npm ci # or pnpm install / yarn install / bun install

      # 执行打包
      - name: Build with VitePress
        run: |
          npm run docs:build # or pnpm docs:build / yarn docs:build / bun run docs:build
          touch docs/.vitepress/dist/.nojekyll

      # 上传打包后的结构, 注意 path, 如果你的不是 docs, 需要修改
      - name: Upload artifact
        uses: actions/upload-pages-artifact@v2
        with:
          path: docs/.vitepress/dist

  #### 部署到 Github Pages 流程 ####
  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    needs: build
    runs-on: ubuntu-latest
    name: Deploy
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v2

4. 执行 Github actions

只要将代码提交到远程仓库,就会自动执行, 如果没有自动执行, 也可以提交代码后, 去手动执行

部署项目到自己的服务器

1.准备步骤

前面创建仓库的步骤不变, 但是需要准备一台公网能够访问的服务器

2.创建 Repository secrets

3.去 Github 创建 Token

去 Github 创建一个 Token 并将它设置到 Repository secrets 中, 名字就叫 TOKEN

4.创建 Github Action 配置文件

这个配置文件是将项目部署到服务器用的, 配置文件 .github/workflows/deploy-to-server.yml

yml
name: Deploy VitePress site to Server

on:
  push:
    tags: ['v*'] # 推送 tag(以v开头) 的时候才执行

  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: pages
  cancel-in-progress: false

jobs:
  #### 构建流程 ####
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      # 安装 node 环境
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: npm

      # 安装项目需要的依赖
      - name: Install dependencies
        run: npm ci

      # 执行打包
      - name: Build with VitePress
        run: |
          npm run docs:build
          touch docs/.vitepress/dist/.nojekyll
          tar -zcvf release.tar.gz run.sh docs/.vitepress/dist
          # 使用 tar 命令压缩需要的文件方便发布release

      # 发布 Release
      - name: Create Release
        id: create_release
        uses: actions/create-release@master
        env:
          # 注意需要创建这个 Repository secrets 变量,
          # 这个的 TOKEN 就是第2,3步添加的 screts 变量的名字
          GITHUB_TOKEN: ${{ secrets.TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: Release ${{ github.ref }}
          draft: false
          prerelease: false

      # 上传打包结果到 Release
      - name: Upload Release Asset
        id: upload-release-asset
        uses: actions/upload-release-asset@master
        env:
          GITHUB_TOKEN: ${{ secrets.TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./release.tar.gz
          asset_name: release.tar.gz
          asset_content_type: application/x-tgz

  #### 部署到服务器流程 ####
  deploy:
    needs: build # 需要等待构建完成
    runs-on: ubuntu-latest
    name: Deploy
    steps:
      - name: Deploy to Server
        id: deployment
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SERVER_ADDR }}
          username: ${{ secrets.SERVER_USER }}
          password: ${{ secrets.SERVER_PASS }}
          port: ${{ secrets.SERVER_PORT }}
          script: |
            rm -rf ~/learn-github-actions-demo    # 清除上次打包缓存, 考虑多次打包的问题
            mkdir -p ~/learn-github-actions-demo  # 创建目录
            cd ~/learn-github-actions-demo        # 进入目录
            # 下载打包结果, 注意这个链接: 必须是你自己的 github 账号名字 和 代码仓库名字
            wget https://github.com/lh5sa/learn-github-actions-demo/releases/latest/download/release.tar.gz -O release.tar.gz 
            tar -zxvf release.tar.gz              # 解压

            # 运行部署脚本(如果你会写 shell 脚本的话, 也可以将上面的步骤写到这个脚本里, 然后直接运行)
            chmod +x ./run.sh && ./run.sh

5. 创建在服务器执行的shell脚本

这里用 docker 方式部署, shell 脚本: ./run.sh

sh
#!/bin/bash

# docker 镜像和容器名
docker_image_name="nginx:stable"
docker_container_name="learn-github-action-demo"

# 先停止原来的
docker stop $docker_container_name
docker rm $docker_container_name

# 启动容器, 注意端口不能被占用, 否则会部署失败
docker run -d \
	-p 80:80 \
	-v $(pwd)/docs/.vitepress/dist:/usr/share/nginx/html \
	--name $docker_container_name $docker_image_name

# 注意路径: 因为现在用的是 nginx:stable 默认的配置文件,
# 并没有映射新的配置文件, 所以容器内的路径必须是这个路径

6.修改 vitepress 配置

由于没有映射自定义的配置文件到 nginx:stable 容器中, 使用的是默认的配置文件, 那么这个步骤必不可少, 否则静态资源加载失败

js
export defalt {
  base: '/',
}

注意:

如果你将 main 分支的代码改成这个这样的话部署到 Github Pages 的的项目资源加载就出问题了, 如果是根据我的文档来的建议再新建一个分支然后创建tag, 提交这个分支的代码就不会触发 deploy.yml 而只会触发 deploy-to-server.yml, 这样的话两个都不会出问题

7.执行 Github Action

注: Git 提交代码时要打 tag 然后提交才会执行(或者去 github 手动执行), 这个执行条件是写在 yml 配置文件中的

部署到服务器注意点

  1. 服务器需要有 docker 环境
  2. 这个部署脚本用的是 80 端口, 不能被占用, 否则会部署失败
  3. 只有提交 tag 的时候, 才会执行这个 Github Actins
  4. 注意 vitepress 的 base 配置

总结归纳, 授人以渔

由于上面两个例子可以发现, 其实配置的核心最重要的就只有以下东西:

  1. 何时执行, 什么时候执行哪个流水线: on 指定触发流水线的事件
  2. 再哪执行, 代码应该在什么样的环境里执行: image 指定任务运行的 docker 镜像
  3. 执行什么, 定义好任务和执行的步骤: jobs & steps 指定有哪些任务,具体如何执行
  4. 如何执行, 任务的步骤具体执行什么: uses 使用什么东西来执行?

其实不止 github actions 是这样的, gitlab cicd 也是这样的, 只不过名字不太一样, 在 gitlab 中 workflow(工作流) 叫 pipeline(流水线) 类似这样的

如何找到更多的构建环境 和 actions?

在上面的例子中, 我们部署到服务器的步骤是:

  1. 将代码下载到 runner 容器中
  2. 安装环境(node 和 pnpm)
  3. 安装依赖并构建(pnpm install && pnpm docs:build)
  4. 将构建结果打包(tar -zcvf release.tar.gz docs/.vitepress/dist)
  5. 上传打包结果到 github Release
  6. 使用 ssh 链接服务器
  7. 下载 github 的 Release
  8. 解压 & 运行部署脚本

但是我不想将 上传打包结果到 github Release, 而是直接上传到服务器应该怎么做?

  1. 去 github marketplace 里找上传命令(如: scp, rsync)对应的 github actions
  2. 使用这个 actions 就可以直接将代码上传到服务器

如何知道 actions 有哪些参数, 如何使用?

github actions 是使用的github上的仓库的,一般是

https://github.com/${user-name}/${actions-name}@${version-tag}

只需要去到它的github主页一般都会有详细的使用介绍, 比如: 下载代码的 action 是: actions/checkout@v3, 那么他的仓库主页就是 https://github.com/actions/checkout

如果想要看它的 v3 版本, 只需要找到v3这个tag并且选中即可

扩展:使用自建的 gitea 和 act_runner

为什么放到这而不是单独一个笔记?

因为 act_runner 的语法和 github actions 的配置文件的语法是差不多的, 95% 是兼容的, 只有一小部分不支持, 具体可以查看文档

安装 gitea 和 act_runner

  1. 需要先运行 gitea-server
  2. 获取相关参数 注册 runner 需要的 token
  3. 获取配置文件
  4. 打开 gitea-runner 注释, 填入需要的参数
  5. 重启服务
yaml
version: '3'

networks:
  gitea:
    external: false

services:
  gitea_server:
    image: gitea/gitea:1.21.2
    container_name: gitea
    hostname: giteaserver
    environment:
      USER_UID: 1000
      USER_GID: 1000
      GITEA__database__DB_TYPE: postgres
      GITEA__database__HOST: 'db:5432'
      GITEA__database__NAME: gitea # 注意要和 db 的 environment 中填的一样
      GITEA__database__USER: admin
      GITEA__database__PASSWD: admin1314
    restart: always
    depends_on:
      - db
    networks:
      - gitea
    volumes:
      - ./gitea_data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - '8000:3000'
      - '8001:22'

  db:
    image: postgres:14
    container_name: postgres
    restart: always
    hostname: postgres_server
    environment:
      POSTGRES_DB: gitea # 数据库名
      POSTGRES_USER: admin # 数据库用户
      POSTGRES_PASSWORD: admin1314 # 数据库密码
    networks:
      - gitea
    ports:
      - '8002:5432'
    volumes:
      - ./postgres_conf:/etc/postgresql
      - ./postgres_data:/var/lib/postgresql/data

  # 生成配置文件 docker run --rm -it --entrypoint=""  gitea/act_runner:latest act_runner generate-config > ./config.yaml
  #gitea-runner:
  #  image: gitea/act_runner:latest
  #  container_name: gitea-runner
  #  restart: always
  #  depends_on:
  #    - gitea-server
  #  networks:
  #    - gitea
  #  volumes:
  #    # 注意需要先生成配置文件,参考: https://docs.gitea.com/usage/actions/act-runner#register-the-runner
  #    - ./gitea_runner/config.yaml:/config.yaml
  #    - ./gitea_runner/data:/data
  #    - /var/run/docker.sock:/var/run/docker.sock
  #  environment:
  #    CONFIG_FILE: /config.yaml
  #    GITEA_INSTANCE_URL: https://gitlab.example.cn
  #    # 注意需要获取注册令牌,参考: https://docs.gitea.com/usage/actions/act-runner#obtain-a-registration-token
  #    GITEA_RUNNER_REGISTRATION_TOKEN: MpVnALiLOGPnqaJduHdPSc7Zjh2dm4XtmNi12345
  #    GITEA_RUNNER_NAME: default-runner

获取注册 runner 需要的 token

runner-token

生成 runner 需要的配置文件

sh
# 这个命令当前目录下生成 runner 需要的配置文件 config.yaml
docker run --entrypoint="" --rm -it gitea/act_runner:latest act_runner generate-config > ./config.yaml

与 github actions 配置文件差异

txt
github 的工作流配置文件是: .github/workflows/demo.yaml
gitea  的工作流配置文件是: .gitea/workflows/demo.yaml

部署 vitepress 项目到服务器

和 github 一样, 注意要创建 Secrets

yaml
name: Deploy VitePress site to Server

on:
  push:
    branches:
      - main # 推送 main 分支的时候执行

jobs:
  #### 构建流程 ####
  build:
    runs-on: ubuntu-latest
    steps:
      - name: checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      # 安装 pnpm
      - name: install pnpm
        uses: pnpm/action-setup@master
        with:
          version: 8

      # 安装 node 环境
      - name: install node
        uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: pnpm

      # 安装项目需要的依赖
      - name: install dependencies
        run: pnpm install

      # 编译源码 -> 压缩需要的文件
      - name: build source codes with vitepress
        run: |
          echo "===== build start ====="
          pnpm docs:build
          ls -al
          mv ./docs/.vitepress/dist ./output
          tar -jcvf artifact.bz2 ./run.sh ./output

      # 将打包的结果到服务器
      - name: upload
        uses: cross-the-world/ssh-scp-ssh-pipelines@latest
        with:
          host: ${{ secrets.SSH_HOST }}
          port: ${{ secrets.SSH_PORT }}
          user: ${{ secrets.SSH_USERNAME }}
          pass: ${{ secrets.SSH_PASSWORD }}
          scp: |
            './artifact.bz2' => '~/'

  #### 链接服务器并执行部署脚本 ####
  deploy:
    needs: build # 需要等待构建完成
    runs-on: ubuntu-latest # 运行在一个 unbuntu 服务器上
    name: Deploy
    steps:
      - name: Deploy to Server
        id: deployment
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          port: ${{ secrets.SSH_PORT }}
          username: ${{ secrets.SSH_USERNAME }}
          password: ${{ secrets.SSH_PASSWORD }}
          script: |
            rm -rf ~/learn-github-actions-demo    # 清除上次打包缓存
            mkdir -p ~/learn-github-actions-demo  # 创建目录
            cd ~/learn-github-actions-demo        # 进入目录
            mv ~/artifact.bz2 ./                  # 移动上传的文件到部署目录
            tar -jxvf artifact.bz2                # 解压
            chmod +x ./run.sh && ./run.sh

Released under the MIT License.