如何拆分GitHub Workflow实现步骤独立徽章并复用构建环境?
问题
我对GitHub Workflow和测试较为陌生,目前在私有GitHub仓库中与十余位同事协作。因不确定第三方服务对仓库的访问权限,我们暂不想使用CircleCI等服务,希望仅借助GitHub Actions完成任务。
当前我们有两个Workflow(分别针对不同Python环境测试同一代码),会在master分支的推送或Pull Request时触发,步骤如下:
- 安装Anaconda
- 创建conda环境(安装依赖)
- 补丁库
- 构建第三方库
- 运行Python单元测试
我们希望能快速知晓新Pull Request中哪部分代码测试失败。目前所有测试由单个文件run_tests.py执行,若拆分该文件为每个测试环节单独创建Workflow,会重复构建环境、补丁库及第三方库,耗时过长。
现咨询:
- 能否在Linux服务器上完成构建后复用该环境,避免重复构建?
- 能否为每个Python测试单独显示成功/失败的状态徽章,而非仅显示整体结果?
- 此类需求是否更适合CircleCI等服务(也欢迎其他推荐)?
当前Python 3环境Workflow配置
name: (Python 3) install and test # Controls when the workflow will run on: # Triggers the workflow on push or pull request events but only for the master branch push: branches: [ master ] pull_request: branches: [ master ] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: # This workflow contains a single job called "build" build: # The type of runner that the job will run on runs-on: ubuntu-latest defaults: run: shell: bash -l {0} # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v2 # Install Anaconda3 and update conda package manager - name: Install Anaconda3 run: | wget https://repo.anaconda.com/archive/Anaconda3-2020.11-Linux-x86_64.sh --quiet bash Anaconda3-2020.11-Linux-x86_64.sh -b -p ~/conda3-env-py3 source ~/conda3-env-py3/bin/activate conda info # Updating the root environment. Install dependencies (YAML) # NOTE: The environment file (yaml) is in the 'etc' folder - name: Install ISF dependencies run: | source ~/conda3-env-py3/bin/activate conda-env create --name isf-py3 --file etc/env-py3.yml --quiet source activate env-py3 conda list # Patch Dask library - name: Patch dask library run: | echo "Patching dask library." source ~/conda3-env-py3/bin/activate source activate env-py3 cd installer python patch_dask_linux64.py conda list # Install pandas-msgpack - name: Install pandas-msgpack run: | echo "Installing pandas-msgpack" git clone https://github.com/abast/pandas-msgpack.git # Applying patch to pandas-msgpack (generating files using newer Cython) git -C pandas-msgpack apply ../installer/pandas_msgpack.patch source ~/conda3-env-py3/bin/activate source activate env-py3 cd pandas-msgpack; python setup.py install pip list --format=freeze | grep pandas # Compile neuron mechanisms - name: Compile neuron mechanisms run: | echo "Compiling neuron mechanisms" source ~/conda3-env-py3/bin/activate source activate env-py3 pushd . cd mechanisms/channels_py3; nrnivmodl popd cd mechanisms/netcon_py3; nrnivmodl # Run tests - name: Testing run: | source ~/conda3-env-py3/bin/activate source activate env-py3 export PYTHONPATH="$(pwd)" dask-scheduler --port=38786 --dashboard-address=38787 & dask-worker localhost:38786 --nthreads 1 --nprocs 4 --memory-limit=100e15 & python run_tests.py
尝试过的操作:在单个GitHub Workflow中完成构建与全量测试。
预期结果:获取各步骤的成功/失败信息,并在README页面显示对应状态徽章。
实际结果:仅能显示Workflow整体成功状态徽章,仅能获取全量测试的成功状态。
解决方案
1. 复用构建环境避免重复构建
可以通过两种方式实现环境复用:
- 缓存conda环境与依赖:使用
actions/cache动作缓存conda的安装目录、创建的环境文件夹、补丁后的库文件以及编译生成的机制文件。缓存的key基于环境配置文件、补丁脚本等关键文件的哈希值生成,只有当这些文件变更时才会重新构建环境。
示例缓存步骤:- name: Cache conda environment uses: actions/cache@v3 with: path: | ~/conda3-env-py3 ~/.conda/envs/isf-py3 pandas-msgpack mechanisms/channels_py3/x86_64 mechanisms/netcon_py3/x86_64 key: conda-py3-${{ hashFiles('etc/env-py3.yml', 'installer/patch_dask_linux64.py', 'installer/pandas_msgpack.patch') }} - 拆分Job实现构建与测试分离:将构建步骤(安装Anaconda、创建环境、补丁、编译)单独作为一个
buildJob,测试步骤拆分为多个独立的testJob。构建完成后,将整个环境打包为Artifact,后续测试Job下载并复用该Artifact,避免重复执行构建操作。
2. 为单个测试显示独立状态徽章
GitHub Actions支持为每个独立Job生成状态徽章,可按以下方式实现:
- 拆分测试为多个Job:在同一个Workflow中,将
run_tests.py拆分为多个测试套件(比如核心功能测试、集成测试等),每个套件对应一个独立的testJob,所有测试Job依赖前面的buildJob。每个Job会生成专属的状态徽章,可在GitHub Actions页面的对应Job详情中获取徽章代码,添加到README中。
示例Workflow结构:jobs: build: # 构建步骤... outputs: env-cache-key: ${{ steps.cache.outputs.cache-primary-key }} test-core: needs: build runs-on: ubuntu-latest steps: # 恢复缓存或下载Artifact... - name: Run core tests run: python run_tests.py --suite core test-integration: needs: build runs-on: ubuntu-latest steps: # 恢复缓存或下载Artifact... - name: Run integration tests run: python run_tests.py --suite integration - 补充测试报告:在测试步骤中生成JUnit格式的测试报告,通过
actions/upload-artifact上传报告,再使用测试报告展示类Action将结果可视化,方便快速定位失败的具体测试用例。
3. 是否适合CircleCI等服务
如果后续团队消除了第三方服务的权限顾虑,CircleCI、GitLab CI等服务在环境复用、测试细粒度展示上有更成熟的内置功能,比如CircleCI的工作空间复用、测试结果分组展示等。但就当前需求而言,GitHub Actions完全可以通过上述方案满足,无需切换服务。如果希望简化配置,可使用conda-incubator/setup-miniconda官方Action替代手动安装Anaconda的脚本,减少维护成本。
内容的提问来源于stack exchange,提问作者Bjorge

