学习一下Github仓库的工作流语法,希望在Github仓库中自动执行测试。
重点关注两类项目所需要的基本测试工作流,分别是跨平台CMake项目和LaTex项目。
概述
Github仓库提供工作流来自动化执行应用的部署,测试和发布等流程。工作流的实质是在Github服务器上提供了几个临时的虚拟环境(Docker),让用户在提交或其他Git行为后触发工作流,然后在虚拟机环境中自动执行相关的指令。
例如,可以使用一个工作流来构建和测试拉取请求,使用另一个工作流在每次创建版本时部署应用程序,
还有另一个工作流程在每次有人打开新问题时添加标签。
注意:
Github仓库支持多个工作流,它们可以同时触发或分别触发。
Github对公开仓库提供的这类服务是无限制的,但是对私有仓库是受限的,每个月提供免费的时间额度和存储额度,超额需要付费。
如果在仓库中触发的一个工作流运行失败了,Github可能通过邮件通知。
一个典型的工作流(workflow)包含:
触发工作流的一个或多个事件
一个或多个作业(job),每个作业都将在运行器机器上执行并运行一系列的一个或多个步骤(step),每个步骤都可以运行指定的脚本或操作(action)
触发工作流的事件通常是:
Git仓库中发生的事件,例如推送到默认分支时、创建版本时
定时触发或手动触发
其他Github支持的触发行为
工作流的配置文件是yaml
格式文件,存储在.github/workflows/
文件夹中,语法规则如下
示例如下
learn-github-actions.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 name: learn-github-actions run-name: ${{ github.actor }} is learning GitHub Actions on: [push ]jobs: check-bats-version: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - run: npm install -g bats - run: bats -v
这个工作流会在代码推送事件发生时自动触发。它定义了一个名为
"check-bats-version" 的任务,将在最新的 Ubuntu
环境上运行,具体行为依次为:
Checkout:将代码从你的仓库检出到运行环境中。
Setup Node:指定 Node.js 的版本为20。
Install Bats:使用 npm 全局安装 Bats,它是一个用于测试 Bash
脚本的测试框架。
Run Bats:最后执行 bats -v
命令。这个命令用于显示系统中安装的 Bats 版本。
触发工作流
常见的工作流触发逻辑是推送到main或者release,以及合并请求时触发,例如
1 2 3 4 5 on: push: branches: [ main , release/** ] pull_request: branches: [ main , release/** ]
有时我们只需要在某些路径或文件发生更改时,才触发工作流,例如
1 2 3 4 5 6 on: push: branches: - 'main' paths: - 'src/utils/**'
这里同时使用了 branches 筛选器和 paths
筛选器,只在这两个筛选器都满足条件时触发工作流。
有时我们只需要在推送形如v1.**
的标签时,触发工作流,例如
1 2 3 4 on: push: tags: - v1.**
有时我们只是进行文档的更新,可以使用下面的格式来避免对应的修改触发测试工作流
1 2 3 4 5 6 on: push: paths-ignore: - 'doc/**' - 'docs/**' - '**.md'
Cpp 项目
CMake跨平台工作流
下面是Github官方推荐的,针对跨平台CMake项目,在最新系统的三大编译器环境 中进行编译测试的工作流配置
(基于系统默认的编译器版本)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 name: CMake on multiple platforms on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: build: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest , windows-latest ] build_type: [Release ] c_compiler: [gcc , clang , cl ] include: - os: windows-latest c_compiler: cl cpp_compiler: cl - os: ubuntu-latest c_compiler: gcc cpp_compiler: g++ - os: ubuntu-latest c_compiler: clang cpp_compiler: clang++ exclude: - os: windows-latest c_compiler: gcc - os: windows-latest c_compiler: clang - os: ubuntu-latest c_compiler: cl steps: - uses: actions/checkout@v3 - name: Set reusable strings id: strings shell: bash run: | echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT" - name: Configure CMake run: > cmake -B ${{ steps.strings.outputs.build-output-dir }} -DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }} -DCMAKE_C_COMPILER=${{ matrix.c_compiler }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -S ${{ github.workspace }} - name: Build run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }} - name: Test working-directory: ${{ steps.strings.outputs.build-output-dir }} run: ctest --build-config ${{ matrix.build_type }}
上面的就是默认提供的配置文件,其实啥也不用改,只是清理了注释,当然也可以修改一下触发条件。
这个配置模板使用了矩阵,看起来比较高级,但是缺点是并没有指定具体的编译器版本,始终使用的是系统默认版本,这也意味着不能使用C++20的部分特性。
CMake跨平台工作流(最新版)
下面提供的是基于最新版编译器(VS2022
,gcc13
和clang18
)的测试工作流(已经足够支持C++20的基础使用)
pipeline-ci.yml,依次调用了三个具体的测试工作流
bvt-msvc14.yml
bvt-gcc13.yml
bvt-clang18.yml
配置文件是参考微软的proxy库的,将编译器版本修改为最新版。 这里
pipeline-ci 指持续集成(Continuous
Integration)中的一个流水线(Pipeline),bvt 指基本验证测试(Basic
Verification Test)。
配置文件 pipeline-ci.yml 具体如下
pipeline-ci.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 name: Test-CI on: push: branches: [ "main" ] paths: - 'src/**' - 'test/**' pull_request: branches: [ "main" ] paths: - 'src/**' - 'test/**' env: BUILD_TYPE: Release jobs: run-bvt-gcc13: uses: ./.github/workflows/bvt-gcc13.yml name: run bvt with g++ 13 run-bvt-clang15: uses: ./.github/workflows/bvt-clang18.yml name: run bvt with clang 18 run-bvt-msvc14: uses: ./.github/workflows/bvt-msvc14.yml name: run bvt with msvc14 (vs2022)
三个工作流是在不同编译器和环境下的基本测试,除了运行环境不同,以及预先下载配置指定的编译器,核心步骤都是一样的:生成,编译,进入构建目录,执行测试。
1 2 3 4 5 6 7 8 9 - name: build with cmake run: | cmake . -B build cmake --build ./build -j8 - name: run tests run: | cd ./build ctest -j8
需要注意的是对于MSVC,在ctest时需要明确构建类型,添加-C Release
选项。
完整的工作流配置文件依次为
bvt-msvc14.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 name: bvt-msvc14 on: workflow_call: inputs: branch: type: string required: false jobs: bvt-msvc14: runs-on: windows-2022 steps: - uses: actions/checkout@v3 with: ref: ${{ inputs.branch }} - name: build with cmake run: | cmake . -B build cmake --build ./build -j8 - name: run tests run: | cd ./build ctest -j8 -C Release
bvt-gcc13.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 name: bvt-gcc13 on: workflow_call: inputs: branch: type: string required: false jobs: bvt-gcc13: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: ref: ${{ inputs.branch }} - name: install gcc 13 run: | sudo apt update sudo apt install -y gcc-13 g++-13 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 13 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 13 - name: check compiler version run: g++ --version - name: build with cmake run: | cmake . -B build cmake --build ./build -j8 - name: run tests run: | cd ./build ctest -j8
bvt-clang18.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 name: bvt-clang18 on: workflow_call: inputs: branch: type: string required: false jobs: bvt-clang18: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 with: ref: ${{ inputs.branch }} - name: install clang 18 run: | wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - sudo apt-add-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main" -y sudo apt update sudo apt install -y clang-18 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/clang-18 18 sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/clang++-18 18 - name: check compiler version run: g++ --version - name: build with cmake run: | cmake . -B build cmake --build ./build -j8 - name: run tests run: | cd ./build ctest -j8
为了复用工作流,可以将上面的文件全部存放在某一个公开仓库中(fenglielie/cmakezero.git
),然后在其它仓库就可以直接调用它,只需要写一个test-ci.yml,例如
test-ci.yml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 name: Test-CI on: push: branches: - 'main' paths: - 'src/utils/**' - 'test/utils/**' env: BUILD_TYPE: Release jobs: run-bvt-gcc13: uses: fenglielie/cmakezero/.github/workflows/bvt-gcc13.yml@main name: run bvt with g++ 13 run-bvt-clang15: uses: fenglielie/cmakezero/.github/workflows/bvt-clang18.yml@main name: run bvt with clang 18 run-bvt-msvc14: uses: fenglielie/cmakezero/.github/workflows/bvt-msvc14.yml@main name: run bvt with msvc14 (vs2022)
LaTeX 项目
编译测试
如果只需要保证LaTex项目可以顺利编译,可以参考下面的配置模板,这里使用XeLaTeX编译main.tex,并且设置工作目录为./latex/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 name: Build LaTeX document on: push: branches: [ main , release/** ] pull_request: branches: [ main , release/** ] jobs: build_release_latex: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Compile LaTeX document uses: xu-cheng/latex-action@v2 with: working_directory: ./latex root_file: main.tex args: -pdf -xelatex -file-line-error -halt-on-error -interaction=nonstopmode
编译测试与发布
如果对LaTeX项目有更多的需求:
将编译生成的PDF文件保留在Git仓库的指定分支(gh_actions_builds)中
将编译生成的PDF文件添加到Release中
配置示例如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 name: Build and Release LaTeX document on: push: branches: [ main ] tags: - 'v*' pull_request: branches: [ main ] workflow_dispatch: jobs: build_release_latex: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Compile LaTeX document uses: xu-cheng/latex-action@v2 with: root_file: main.tex args: -pdf -xelatex -file-line-error -halt-on-error -interaction=nonstopmode - name: Stash PDF run: | mv main.pdf $HOME # cache the file - name: Create Branch uses: peterjgrainger/action-create-branch@v2.0.1 env: GITHUB_TOKEN: ${{ secrets.GH_LATEX_TEST_TOKEN }} with: branch: gh_actions_builds - name: Checkout gh_actions_builds Branch uses: actions/checkout@v3 with: ref: gh_actions_builds - name: Commit PDF run: | git config --local user.email "fenglielie@gmail.com" git config --local user.name "fenglielie" mv $HOME/main.pdf $(pwd) # bring it back git add -f main.pdf git commit -m "Updated by GitHub Action Automatically" - name: Push PDF uses: ad-m/github-push-action@master with: branch: gh_actions_builds force: false github_token: ${{ secrets.GH_LATEX_TEST_TOKEN }} - name: Release uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/' ) with: files: main.pdf env: GITHUB_TOKEN: ${{ secrets.GH_LATEX_TEST_TOKEN }}
注意:由于需要提交,这里需要配置用户名和邮箱,创建和切换分支,并且需要在Github中设置并提供一个GITHUB_TOKEN
,否则在虚拟环境中默认是没有权限对仓库进行任何修改操作的。
补充
看到了一个对于非英文的issue自动翻译的workflow ,记录下来,以后可能有用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 name: 'issue-translator' on: issue_comment: types: [created ] issues: types: [opened ] jobs: build: runs-on: ubuntu-latest steps: - uses: usthe/issues-translate-action@v2.7 with: IS_MODIFY_TITLE: false CUSTOM_BOT_NOTE: Issue is not in English. It has been translated automatically.