如何在GitHub Actions策略矩阵中传入动态值?解决env变量识别报错问题
解决GitHub Actions策略矩阵中传入动态值的问题
你遇到的报错原因很明确:GitHub Actions的策略矩阵是在工作流初始化阶段就完成解析的,这时候你定义的env.FORMULA和steps.get-tag.outputs.TAG_NAME都还没被初始化(毕竟get-tag步骤是在test job里才会运行的),所以直接在matrix里引用这些动态值肯定会报错。
下面给你两种可行的解决方案,第一种是最通用的,适合大多数动态矩阵场景:
方法一:用前置Job生成动态矩阵
核心思路是先创建一个专门的Job来生成包含动态值的矩阵,然后让后续的测试Job引用这个生成好的矩阵。这样就能避开初始化阶段无法访问动态值的限制。
完整的工作流示例如下:
env: FORMULA: testFormula jobs: # 第一步:生成动态矩阵 generate-matrix: runs-on: ubuntu-latest outputs: matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - name: Getting latest tag id: get-tag run: | # 修正原代码里的多余右括号 echo "::set-output name=TAG_NAME::2.3.4" - name: Construct dynamic matrix id: set-matrix run: | TAG_NAME="${{ steps.get-tag.outputs.TAG_NAME }}" FORMULA="${{ env.FORMULA }}" # 构造矩阵的JSON数组,注意格式要正确 MATRIX=$(cat <<EOF [ {"os": "ubuntu-latest", "asset_name": "$FORMULA-$TAG_NAME", "command_name": "echo 'matrix1'"}, {"os": "ubuntu-latest", "artifact_name": "$FORMULA_$TAG_NAME-1_amd64.deb", "asset_name": "$FORMULA-$TAG_NAME.deb", "command_name": "echo 'matrix2'"}, {"os": "macos-latest", "artifact_name": "$FORMULA-v$TAG_NAME-x86.exe", "asset_name": "$FORMULA-$TAG_NAME.exe", "command_name": "echo 'matrix3'"}, {"os": "macos-latest", "artifact_name": "macos/$FORMULA-v$TAG_NAME.pkg", "asset_name": "$FORMULA-$TAG_NAME.pkg", "command_name": "echo 'matrix4'"} ] EOF ) # 把矩阵输出为Job级别的输出 echo "::set-output name=matrix::$MATRIX" # 第二步:使用生成好的动态矩阵运行测试 test: name: Test for ${{ matrix.os }} runs-on: ${{ matrix.os }} needs: generate-matrix strategy: fail-fast: false matrix: include: ${{ fromJSON(needs.generate-matrix.outputs.matrix) }} steps: - name: Run command run: ${{ matrix.command_name }} # 这里可以直接使用矩阵里的动态值,比如上传artifact或者asset - name: Example use dynamic value run: | echo "Artifact name: ${{ matrix.artifact_name }}" echo "Asset name: ${{ matrix.asset_name }}"
关键说明:
generate-matrixJob先完成所有动态值的计算(比如获取TAG_NAME),然后构造出完整的矩阵JSON结构。- 通过
fromJSON()函数把输出的JSON字符串转换成GitHub Actions能识别的矩阵格式。 testJob通过needs: generate-matrix确保前置Job完成后才运行,这样就能拿到动态生成的矩阵了。
方法二:Job级别Env结合矩阵静态值(适合简单场景)
如果你的动态值不需要在矩阵定义阶段就被引用,只是在后续步骤中使用,也可以把动态值放到Job级别的Env里,矩阵只定义静态部分,然后在步骤中拼接:
env: FORMULA: testFormula jobs: test: name: Test for ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - os: ubuntu-latest asset_suffix: "" command_name: echo "matrix1" - os: ubuntu-latest artifact_suffix: "_TAG-1_amd64.deb" asset_suffix: ".deb" command_name: echo "matrix2" - os: macos-latest artifact_suffix: "-vTAG-x86.exe" asset_suffix: ".exe" command_name: echo "matrix3" - os: macos-latest artifact_suffix: "macos/-vTAG.pkg" asset_suffix: ".pkg" command_name: echo "matrix4" steps: - name: Getting latest tag id: get-tag run: | TAG="2.3.4" echo "TAG_NAME=$TAG" >> $GITHUB_ENV - name: Use dynamic values run: | # 替换静态后缀里的TAG占位符,拼接出最终文件名 ARTIFACT_NAME="${{ env.FORMULA }}${{ matrix.artifact_suffix//TAG/${{ env.TAG_NAME }} }}" ASSET_NAME="${{ env.FORMULA }}-${{ env.TAG_NAME }}${{ matrix.asset_suffix }}" echo "Artifact: $ARTIFACT_NAME" echo "Asset: $ASSET_NAME" ${{ matrix.command_name }}
不过这种方法的局限性在于,矩阵本身还是静态的,只是通过后续步骤拼接动态值,所以如果你的场景需要在矩阵定义阶段就用到动态值(比如不同os对应不同的动态生成文件名),还是方法一更合适。
内容的提问来源于stack exchange,提问作者lakshmiravali rimmalapudi
相关产品推荐
相关产品推荐

