GitHub Action使用通配符生成测试项目矩阵失败求助
GitHub Actions自动生成单元测试项目矩阵失败的排查与解决
我正在优化单仓库(mono-repo)的CI流程,暂不考虑拆分仓库。当前仓库包含约12个单元测试项目,同时新增了依赖Docker镜像(如SQL、LocalStack)的集成测试项目,需要分开运行单元测试和集成测试,且不想硬编码项目列表,避免新增测试项目时其他开发者遗漏更新。
仓库目录结构如下:
src/ -> Foo/... tests/ -> Foo/ -> Foo.UnitTests/Foo.UnitTests.csproj -> Foo.IntegrationTests/Foo.IntegrationTests.csproj -> Bar/ -> Bar.UnitTests/Bar.UnitTests.csproj -> Bar.IntegrationTests/Bar.IntegrationTests.csproj ...
因为dotnet test不支持通过正则过滤csproj文件,常规过滤参数也因命名空间不一致无法使用,所以尝试编写GitHub Action配置自动生成测试项目矩阵,配置如下:
unit-test-list: name: unit-test-list runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - uses: actions/checkout@v2 - id: set-matrix run: echo "name=matrix::$(ls ./**/*.UnitTests.csproj | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT unit-test: name: unit-test needs: [build,unit-test-list] runs-on: ubuntu-latest strategy: fail-fast: true matrix: csproj: ${{ fromJson(needs.unit-test-list.outputs.matrix) }} steps: - uses: actions/checkout@v2 - name: Setup .NET uses: actions/setup-dotnet@v1 with: dotnet-version: ${{ env.DOTNET_VERSION }} - name: Install dependencies run: dotnet restore - name: Run *.UnitTests run: dotnet test ${{ matrix.csproj }} --no-restore --verbosity quiet
遇到的问题
- 使用
ls ./**/*.UnitTests.csproj时,始终报错ls: cannot access './**/*.UnitTests.csproj': No such file or directory,无法找到对应文件。 - 硬编码路径如
ls ./tests/Foo/Foo.UnitTests/Foo.UnitTests.csproj时,ls命令不再报错,但后续unit-test任务因接收到空字符串失败,错误信息:
Build and Test Solution: .github#L1 Error when evaluating 'strategy' for job 'unit-test'. .github/workflows/on-pull-request.yml (Line: 44, Col: 17): Error parsing fromJson,.github/workflows/on-pull-request.yml (Line: 44, Col: 17): Error reading JToken from JsonReader. Path '', line 0, position 0.,.github/workflows/on-pull-request.yml (Line: 44, Col: 17): Unexpected value ''
直接硬编码矩阵值csproj: ["./tests/Foo/Foo.UnitTests/Foo.UnitTests.csproj","./tests/Bar/Bar.UnitTests/Bar.UnitTests.csproj"]可正常运行,说明问题出在列表生成代码中。
错误原因与修复方案
1. 输出格式错误(导致矩阵为空)
原来的echo命令格式不符合GitHub Actions的输出规范,正确格式应为echo "KEY=VALUE" >> $GITHUB_OUTPUT。你写的echo "name=matrix::$(...)"会让GitHub解析出键名为name而非matrix,最终导致unit-test任务获取的matrix值为空。
2. ls不支持**递归通配(导致文件查找失败)
默认bash环境中,ls不支持**的递归匹配(需手动开启globstar选项),改用find命令递归查找更可靠,无需依赖shell配置。
最终修复后的set-matrix步骤
- id: set-matrix run: | # 使用find递归查找所有UnitTests.csproj文件,转换为JSON数组 PROJECTS=$(find ./tests -name "*.UnitTests.csproj" | jq -R -s -c 'split("\n")[:-1]') # 确保输出格式正确 echo "matrix=$PROJECTS" >> $GITHUB_OUTPUT
额外优化点
添加空值判断,若未找到单元测试项目则输出空数组[],避免fromJson解析失败:
- id: set-matrix run: | PROJECTS=$(find ./tests -name "*.UnitTests.csproj" | jq -R -s -c 'split("\n")[:-1]') # 处理空结果的情况 if [ -z "$PROJECTS" ] || [ "$PROJECTS" == '""' ]; then PROJECTS="[]" fi echo "matrix=$PROJECTS" >> $GITHUB_OUTPUT
内容的提问来源于stack exchange,提问作者JALLRED
相关产品推荐
相关产品推荐

