GitHub Actions矩阵作业条件为假仍运行的问题及优化咨询
问题解答
1. 为何条件全为假时docker作业仍会被触发?
当所有isCollector/isWorker/isApi/isWebhook都为false时,你的exclude规则会把所有矩阵条目全部排除,此时矩阵没有任何有效运行项。但GitHub Actions的默认逻辑是:如果矩阵筛选后无剩余条目,作业仍会执行一次,但所有matrix变量都会为空。这就是docker作业启动且无法访问${{ matrix.image }}的原因——此时根本不存在matrix数据。
2. 更优的条件结构实现
以下两种方案可彻底阻止docker作业在无变更时运行:
方案一:作业级别添加全局条件判断
直接在docker作业上增加if条件,判断是否有至少一个需要构建的镜像或依赖库发生变更,无变更时直接跳过整个作业:
docker: name: Build and push Docker Images runs-on: ubuntu-latest needs: changes timeout-minutes: 30 # 新增:仅当有需要构建的目标时才启动作业 if: | needs.changes.outputs.collector == 'true' || needs.changes.outputs.workers == 'true' || needs.changes.outputs.api == 'true' || needs.changes.outputs.webhook == 'true' || needs.changes.outputs.library == 'true' strategy: matrix: image: - collector - workers - api - webhook # 简化条件映射,每个镜像对应单独的构建判断 include: - image: collector shouldBuild: ${{ needs.changes.outputs.collector == 'true' || needs.changes.outputs.library == 'true' }} - image: workers shouldBuild: ${{ needs.changes.outputs.workers == 'true' || needs.changes.outputs.library == 'true' }} - image: api shouldBuild: ${{ needs.changes.outputs.api == 'true' || needs.changes.outputs.library == 'true' }} - image: webhook shouldBuild: ${{ needs.changes.outputs.webhook == 'true' || needs.changes.outputs.library == 'true' }} exclude: - shouldBuild: false
方案二:动态生成构建矩阵(更简洁灵活)
通过changes作业直接输出需要构建的镜像列表,避免冗余的矩阵条件配置:
首先修改changes作业,新增生成目标镜像列表的步骤:
changes: name: Detect changes runs-on: ubuntu-latest outputs: imagesToBuild: ${{ steps.generate-images.outputs.imagesToBuild }} all: ${{ steps.filter.outputs.changes }} timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v1.4.7 - name: Filter changes uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: filter with: filters: | library: - 'package.json' - 'package-lock.json' - 'shared/**' workers: - 'workers/**' - 'prisma/**' collector: - 'collector/**' api: - 'api/**' webhook: - 'webhook/**' - name: Generate images to build id: generate-images run: | images=() # 依赖库变更则构建所有镜像 if [ "${{ steps.filter.outputs.library }}" = "true" ]; then images=("collector" "workers" "api" "webhook") else # 逐个判断单个镜像是否需要构建 [ "${{ steps.filter.outputs.collector }}" = "true" ] && images+=("collector") [ "${{ steps.filter.outputs.workers }}" = "true" ] && images+=("workers") [ "${{ steps.filter.outputs.api }}" = "true" ] && images+=("api") [ "${{ steps.filter.outputs.webhook }}" = "true" ] && images+=("webhook") fi # 转换为JSON数组输出给后续作业 echo "imagesToBuild=$(jq -cn '$ARGS.positional' --args "${images[@]}")" >> "$GITHUB_OUTPUT"
再修改docker作业,直接使用动态生成的矩阵:
docker: name: Build and push Docker Images runs-on: ubuntu-latest needs: changes timeout-minutes: 30 # 仅当有需要构建的镜像时启动作业 if: ${{ fromJSON(needs.changes.outputs.imagesToBuild) != '[]' }} strategy: matrix: image: ${{ fromJSON(needs.changes.outputs.imagesToBuild) }}
该方案扩展性更强,新增镜像时仅需在changes作业的判断逻辑中添加即可,无需修改docker作业的矩阵配置。
内容的提问来源于stack exchange,提问作者semural
相关产品推荐
相关产品推荐

