You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GitLab CI/CD中snyk_summary失败后流水线仍执行build问题求助

问题

我在使用GitLab CI/CD时,test阶段执行snyk_dependency_scan、snyk_code_scan、snyk_container_scan三个Snyk安全扫描任务,随后由snyk_summary汇总结果,发现漏洞就终止流水线。但目前snyk_summary以exit 1失败后,build阶段任务仍会运行完成。我已经验证了以下内容:

  • snyk_summary任务已正确标记为失败(显示红色);
  • build任务配置了needs依赖snyk_summary且optional: false;
  • build任务设置了when: on_success。

想请教GitLab的needs或when配置是否有我忽略的细节?如何确保snyk_summary失败后流水线停止?

相关配置代码

主.gitlab-ci.yml配置

stages:
- test
- build
- deploy

include:
  - local: templates/snyk-scan-template.yml

snyk_dependency_scan:
  extends: .snyk_dependency_scan
  rules:
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main" || $CI_COMMIT_BRANCH == "main"'
      when: always
    - when: never

snyk_code_scan:
  extends: .snyk_code_scan
  rules:
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main" || $CI_COMMIT_BRANCH == "main"'
      when: always
    - when: never

snyk_container_scan:
  extends: .snyk_container_scan
  rules:
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main" || $CI_COMMIT_BRANCH == "main"'
      when: always
    - when: never

snyk_summary:
  extends: .snyk_summary
  needs:
    - snyk_dependency_scan
    - snyk_code_scan
    - snyk_container_scan
  rules:
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^(develop|main)$/ || $CI_COMMIT_BRANCH == "main"'
      when: always
    - when: never
  allow_failure: false

build:
  stage: build
  image: docker:latest
  needs:
    - job: snyk_summary
      optional: false
  script:
    - echo "Building project..."
  rules:
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^(develop|main)$/ || $CI_COMMIT_BRANCH == "main"'
      when: always
    - when: never
  when: on_success

deploy:
  stage: deploy
  image: alpine:latest
  needs: [build]
  script:
    - echo "Deploying to production..."
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
      when: always

Snyk扫描模板配置

.snyk_common:
  image: node:18
  before_script:
    - apt-get update && apt-get install -y python3 python3-venv python3-pip jq curl
    - python3 -m venv .venv
    - source .venv/bin/activate
    - pip install -r requirements.txt
    - npm install -g snyk snyk-to-html
    - snyk auth $SNYK_TOKEN

.snyk_dependency_scan:
  extends: .snyk_common
  stage: test
  script:
    - snyk test --severity-threshold=high --json > snyk_dep_results.json
    
  artifacts:
    when: always
    paths:
      - snyk_dep_results.json

.snyk_code_scan:
  extends: .snyk_common
  stage: test
  script:
    - snyk ignore --file-path=.venv
    - snyk code test --all-projects --severity-threshold=high --exclude=.venv --json > snyk_code_results.json
    
  artifacts:
    when: always
    paths:
      - snyk_code_results.json
    

.snyk_container_scan:
  stage: test
  image:
    name: snyk/snyk:docker
    entrypoint: [""]
  services:
    - docker:20.10.11-dind
  variables:
    DOCKER_HOST: tcp://docker:2375
    DOCKER_TLS_CERTDIR: ""
  script:
    - apk add --no-cache nodejs npm  # or use apt-get if Debian-based
    - npm install -g snyk-to-html
    - docker build -t app:$CI_COMMIT_SHORT_SHA .
    - snyk auth $SNYK_TOKEN
    - snyk container test app:$CI_COMMIT_SHORT_SHA --file=Dockerfile --severity-threshold=high --json > snyk_container_results.json

  artifacts:
    when: always
    paths:
      - snyk_container_results.json
      

.snyk_summary:
  stage: test
  image: node:18
  script:
    - apt-get update && apt-get install -y jq
    - |
      echo "Evaluating Snyk scan results..."
      oss_issues=$(jq '.uniqueCount // 0' snyk_dep_results.json || echo 0)
      code_issues=$(jq '.runs[0].results | length' snyk_code_results.json || echo 0)
      container_issues=0
      if [ -f snyk_container_results.json ]; then
        container_issues=$(jq '.vulnerabilities | length' snyk_container_results.json || echo 0)
      fi

      echo "OSS issues: $oss_issues"
      echo "Code issues: $code_issues"
      echo "Container issues: $container_issues"

      if [ "$oss_issues" -gt 0 ] || [ "$code_issues" -gt 0 ] || [ "$container_issues" -gt 0 ]; then
        echo "❌ Snyk found vulnerabilities. Failing pipeline."
        exit 1
      else
        echo "✅ No vulnerabilities found."
      fi
  allow_failure: false

问题分析与解决方案

核心问题:rules中的when: always覆盖了外层的when: on_success

GitLab CI的优先级规则明确:rules内的when设置会直接覆盖任务顶层的when配置。你的build任务在rules里指定了when: always,这意味着只要满足if条件,不管snyk_summary是否成功,build都会强制执行,完全忽略了后续的when: on_success。

修复方案

修改build任务的rules,将when: always替换为when: on_success,确保只有在依赖的snyk_summary成功时才执行构建:

build:
  stage: build
  image: docker:latest
  needs:
    - job: snyk_summary
      optional: false
  script:
    - echo "Building project..."
  rules:
    - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^(develop|main)$/ || $CI_COMMIT_BRANCH == "main"'
      when: on_success  # 修改此处的when值
    - when: never

额外检查点

  1. 确认snyk_summary的allow_failure确实为false(你已配置),否则即使任务失败,GitLab也会判定为"成功",导致后续任务继续执行。
  2. 检查needs配置准确性:确保build的needs仅依赖snyk_summary,无其他额外依赖干扰执行逻辑。
  3. 验证GitLab版本:较旧版本可能存在needs与rules交互的bug,建议使用GitLab 13.10+版本(该版本修复了多个相关优先级问题)。

内容的提问来源于stack exchange,提问作者Shashi Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 05:19:56