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
额外检查点
- 确认
snyk_summary的allow_failure确实为false(你已配置),否则即使任务失败,GitLab也会判定为"成功",导致后续任务继续执行。 - 检查
needs配置准确性:确保build的needs仅依赖snyk_summary,无其他额外依赖干扰执行逻辑。 - 验证GitLab版本:较旧版本可能存在
needs与rules交互的bug,建议使用GitLab 13.10+版本(该版本修复了多个相关优先级问题)。
内容的提问来源于stack exchange,提问作者Shashi Kumar
相关产品推荐
相关产品推荐

