GitHub Actions中Job生成数组用作Matrix时出错求助
问题分析与解决方案
错误原因
GitHub Actions 的 matrix 要求传入合法的 JSON 数组,你当前生成的数组格式不符合标准:
- 脚本生成的是
[Directory1/Dockerfile](元素无引号),这不是有效的 JSON 字符串数组 - 硬编码时你用了
["Directory1/Dockerfile"](元素带双引号),属于合法 JSON 格式,因此能正常运行
修正后的工作流
name: Identify Changed Files and Directories on: [push] jobs: identify-changes: runs-on: ubuntu-latest outputs: matrix: ${{ steps.extract.outputs.matrix }} steps: - name: Checkout code uses: actions/checkout@v3 - name: Fetch history run: git fetch origin - name: Git Diff uses: technote-space/get-diff-action@v6 with: PATTERNS: | **/*.js **/*/*.js **/Dockerfile - name: Extract Dockerfile paths id: extract run: | dockerfile_matrix=() substrings=() # 安全提取所有变更路径(兼容含空格的路径) while IFS= read -r path; do substrings+=("$path") done < <(echo "$GIT_DIFF_FILTERED" | xargs -n1 | sed "s/'//g") # 遍历路径,收集对应的Dockerfile for substring in "${substrings[@]}"; do # 提取根目录 IFS='/' read -ra parts <<< "$substring" root_directory="${parts[0]}" # 查找根目录下的Dockerfile(只取第一个,避免多文件重复) DOCKERFILE=$(find "$root_directory" -type f -name "Dockerfile" | head -n1) if [[ ! -z "$DOCKERFILE" ]]; then # 去重,避免重复添加同一个Dockerfile if [[ ! " ${dockerfile_matrix[@]} " =~ " ${DOCKERFILE} " ]]; then dockerfile_matrix+=("$DOCKERFILE") fi fi done # 用jq生成合法的JSON数组(自动处理特殊字符转义) json_array_str=$(printf '%s\n' "${dockerfile_matrix[@]}" | jq -R . | jq -s .) # 输出到GitHub变量 echo "matrix=$json_array_str" >> $GITHUB_OUTPUT echo $json_array_str build: runs-on: ubuntu-latest needs: identify-changes continue-on-error: true strategy: matrix: dockerfile: ${{ fromJSON(needs.identify-changes.outputs.matrix) }} steps: - name: Checkout code uses: actions/checkout@v3 - name: Build Docker images run: | echo "${{ matrix.dockerfile }}"
关键修改点
- 路径提取优化:用
xargs+ 循环读取的方式处理变更路径,兼容含空格的路径,避免分割错误 - 去重处理:添加Dockerfile路径去重逻辑,防止同一个目录的Dockerfile被重复添加
- 合法JSON生成:用
jq工具生成标准JSON数组,确保每个元素被双引号包裹,自动处理特殊字符转义 - matrix解析:在
buildjob的matrix中,用fromJSON()函数解析输出的JSON字符串,确保GitHub能正确识别为数组
替代方案(不依赖jq)
如果环境中没有jq,可以手动拼接合法的JSON数组:
# 手动生成JSON数组元素(转义双引号) json_elements=() for dockerfile in "${dockerfile_matrix[@]}"; do escaped=$(printf '%s' "$dockerfile" | sed 's/"/\\"/g') json_elements+=("\"$escaped\"") done # 拼接为数组字符串 json_array_str="[${json_elements[*]}]"
内容的提问来源于stack exchange,提问作者NeonOni
相关产品推荐
相关产品推荐

