GitHub Actions并发与可锁定资源配置问题求助
实现GitHub Actions中的可锁定资源池(无需公共Action)
核心思路
通过全局并发锁控制资源分配流程的串行执行,再利用GitHub API检查每个资源的占用状态,自动分配第一个未被占用的资源,最后针对该资源设置专属并发锁确保同一时间仅一个测试任务使用它。
具体实现
- 配置工作流权限:需要
actions:read权限来查询运行中的工作流状态 - 资源分配Job:遍历所有可用资源,通过API检查对应并发组的运行状态,找到第一个空闲资源
- 测试Job:使用分配到的资源执行测试,同时针对该资源设置并发锁
on: workflow_call: inputs: array: type: string required: false # 全局并发锁:确保同一时间只有一个工作流在执行资源分配 concurrency: group: pytest-resource-pool cancel-in-progress: false jobs: allocate-resource: runs-on: ubuntu-latest permissions: actions: read # 授权读取工作流运行状态 outputs: selected-resource: ${{ steps.find-free-resource.outputs.resource }} steps: - name: Define available resources id: set-resources run: | # 定义所有可测试资源列表,也可从inputs传入转换 RESOURCES='["resource-a", "resource-b", "resource-c"]' echo "resources=$RESOURCES" >> $GITHUB_OUTPUT - name: Find first free resource id: find-free-resource run: | RESOURCES=$(echo '${{ steps.set-resources.outputs.resources }}' | jq -r '.[]') for RESOURCE in $RESOURCES; do # 检查该资源对应的并发组是否有运行中的工作流 RUNNING=$(gh api /repos/${{ github.repository }}/actions/runs \ -f status=in_progress \ -f filter=all \ --jq '.workflow_runs[] | select(.name == "你的工作流名称" and .head_branch == "${{ github.head_ref }}") | .concurrency_group' | grep "pytest-$RESOURCE") if [ -z "$RUNNING" ]; then echo "resource=$RESOURCE" >> $GITHUB_OUTPUT exit 0 fi done # 所有资源被占用时的处理逻辑,可按需调整 echo "所有资源均被占用,退出工作流" exit 1 test: needs: allocate-resource runs-on: ubuntu-latest # 针对选中的资源设置并发锁,避免同一资源被同时使用 concurrency: group: pytest-${{ needs.allocate-resource.outputs.selected-resource }} cancel-in-progress: false steps: - name: Run tests with selected resource run: | echo "使用资源 ${{ needs.allocate-resource.outputs.selected-resource }} 执行单元测试" # 替换为实际测试命令,比如 pytest --resource ${{ needs.allocate-resource.outputs.selected-resource }}
关键细节说明
- 全局并发锁:
pytest-resource-pool组避免多个工作流同时执行资源分配,防止抢占冲突 - 资源占用检查:通过
gh api筛选当前运行中的工作流,判断对应资源的并发组是否被占用 - 资源专属锁:测试Job的
concurrency组绑定选中资源,保证同一时间仅一个测试任务使用该资源
无API调用替代方案
如果限制使用API,可通过分支模拟锁实现:
- 为每个资源创建专属分支(如
lock-resource-a) - 分配资源时尝试推送空提交到对应分支,成功则表示资源空闲(需开启分支保护禁止强制推送)
- 测试完成后删除分支释放资源
这种方式无需API权限,但需额外管理分支和保护规则,适合对API调用有限制的场景。
内容的提问来源于stack exchange,提问作者TaylorNielson
相关产品推荐
相关产品推荐

