github actions 实现自动部署 github pages 和 android 出 build

74 阅读3分钟

最近对 CI/CD 有点兴趣,也希望用 CI/CD 来简化我的一些工作,刚好 github 提供了 github actions 供用户使用,因此开展了下列的实践

需求

我有个项目是 github-pages-project,使用的框架是 vue3,每次我修改了代码,都会手动执行 yarn build 的操作,然后复制生成的 dist 文件夹里面的内容,覆盖我另一个项目 <username>.github.io 里面的内容,再提交到远程,以此完成 github pages 内容的更新

希望的是,当 push 代码后,自动将 build 后的 dist 文件夹里面的内容自动推送到 <username>.github.io

实现

在项目根目录下,创建 .github/workflows 文件夹(如果还不存在),并在其中创建一个新的 YAML 文件(例如 deploy.yml

先实现简单的,在 GitHub Actions 中,on 是用于定义工作流触发条件的关键字。通过 on,你可以指定在什么事件发生时触发工作流。例如,代码推送、拉取请求、新标签创建等。我们通过 on 设置 push 时触发

actions/checkout@v2 是 GitHub Actions 中一个常用的操作(action)。它的主要作用是将仓库的代码签出到 GitHub Actions 运行器(Runner)上,以便后续的构建、测试和部署步骤能够访问和操作这些代码

actions/setup-node@v2 是 GitHub Actions 中一个常用的操作(action),用于在运行器(Runner)上设置 Node.js 环境。这个操作帮助你在工作流中指定需要的 Node.js 版本,并配置相应的环境,以便后续的步骤能够运行 Node.js 应用程序或脚本

上述两步在前端项目中基本上是必要的

然后很容易看懂了,yarn installyarn build 分别是安装和构建命令

name: Build and Deploy

on:
  push:
    branches:
      - main

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          node-version: '20.11.1'

      - name: Install dependencies
        run: yarn install

      - name: Build project
        run: yarn build

比较麻烦的是将 dist 文件夹下的代码上传到另一个仓库,第一个问题是权限,我们可以使用 Personal Access Token(简称 PAT),创建步骤是 GitHub > Settings > Developer settings > Personal access tokens,生成一个新的 token,选择 repo 权限,这个 token 就是 PAT,然后使用这个 token ,我们就可以做提交的步骤了

PAT 为了安全,通常并不能明文显示,当然,如果你的项目是 private 的,可以明文,但明文终究不是好的实践;将敏感信息存储在 GitHub Secrets 中是一个最佳实践,进入你的 GitHub 仓库 > Settings。在左侧栏中点击 Secrets and variables,然后选择 Actions。点击 New repository secret,名称为 PERSONAL_TOKEN,并粘贴刚生成的 token,在 yml 中可通过 ${{ secrets.PERSONAL_TOKEN }} 安全地引用该 token

另一个问题是默认的分支,有些可能是 master,有些可能是 main,因此在初始化时指定分支名称为 main

github-actions[bot] 是一个特殊的用户账号,由 GitHub 专门为 GitHub Actions 创建和管理。它的主要作用是代表 GitHub Actions 在你的仓库中执行自动化任务。这个用户账号自动生成,并且在运行工作流时具有特定的权限和标识

由于是 github pages 项目,因此我可以直接 --force,如果你是其他类型的项目,这方面切记要谨慎设置

      - name: Push to another repository
        env:
          PERSONAL_TOKEN: ${{ secrets.PERSONAL_TOKEN }}
          USER_NAME: your-username
        run: |
          git config --global user.name 'github-actions[bot]'
          git config --global user.email 'github-actions[bot]@users.noreply.github.com'
          cd dist
          git init -b main
          git add .
          git commit -m 'Deploy from GitHub Actions'
          git push --force "https://${{ env.USER_NAME }}:${{ env.PERSONAL_TOKEN }}@github.com/${{ env.USER_NAME }}/${{ env.USER_NAME }}.github.io.git" main

验证

github-pages-project 的网址上看到上方有个 Actions 的 tab,可以看到每次提交是否执行成功,如果执行失败,也能看到报错。在 <username>.github.io 上可以看到确实提交成功了。打开 https://<username>.github.io,看到代码已成功更改,说明实践成功

android 出 build

如果是 android 或 iOS 项目,github 也提供了 github release 以供实践,在 Code tab 下,你可以看到右边有个 release 的入口,你可以手动上传生成的 apk,同样也可以配置 github actions 来实现自动出 build

下面是一个 flutter 项目的配置文件 release.yml ,flutter 生成的 apk 路径与其他 android 项目不同,可根据需要配置路径,同样用到了 PERSONAL_TOKEN ,这个 env 变量可以用前面生成的,但需要每个项目都设置一次

name: Build and Release

on:
  push:
    branches:
      - main

jobs:
  build-and-release:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Set up Flutter
        uses: subosito/flutter-action@v2
        with:
          flutter-version: "3.24.0" # 根据需要设置 Flutter 版本

      - name: Install dependencies
        run: flutter pub get

      - name: Build APK
        run: flutter build apk --release

      - name: Create Release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.PERSONAL_TOKEN }}
          VERSION_NAME: "v1.0.0" # 根据项目情况配置
        with:
          tag_name: ${{ env.VERSION_NAME }}
          release_name: "Release ${{ env.VERSION_NAME }}"
          body: "自动创建的 Release"
          draft: false
          prerelease: false

      - name: Upload APK to Release
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.PERSONAL_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: build/app/outputs/flutter-apk/app-release.apk
          asset_name: app-release.apk
          asset_content_type: application/vnd.android.package-archive