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

GitLab CI changes规则语法及配置不生效问题排查

问题修复方案

你当前配置存在两类核心错误,分别导致build阶段永不触发、deploy阶段无前置校验直接运行的问题,具体修复方式如下:

一、修正changes字段的匹配语法

GitLab CI的changes规则使用glob路径匹配,你当前的写法存在3个致命问题:

  • 星号前加了不必要的反斜杠转义,会让规则去匹配文件名字面量为*.ts/*.json的文件,无法匹配真实业务文件
  • 单星号*仅能匹配仓库根目录下的文件,无法递归匹配src下多层嵌套子目录内的.ts文件、resources下的嵌套资源
  • Dockerfile路径写错,实际文件存放在.docker子目录下,根目录无对应文件,永远匹配不到

正确的changes匹配规则

直接替换原有changes段即可,规则会精确匹配你需要的核心文件范围,不会误匹配根目录下的eslint、tsconfig等无关配置文件:

changes:
  # 递归匹配所有层级目录下的.ts文件,覆盖src下所有嵌套子目录
  - "**/*.ts"
  # 匹配根目录下的依赖配置文件
  - "package.json"
  - "package-lock.json"
  # 匹配.docker目录下的Dockerfile
  - ".docker/Dockerfile"
  # 匹配resources目录下所有文件(含嵌套子目录的图片、json配置)
  - "resources/**/*"
  # 匹配src目录下所有文件(含嵌套子目录)
  - "src/**/*"

规则说明:路径外包裹双引号是为了避免YAML解析时特殊字符转义异常;**是递归通配符,可匹配任意层级的子目录。

二、修正deploy阶段的触发逻辑

你当前的deploy规则仅校验了分支为main,缺少两个关键限制:

  • 没有绑定对build阶段的成功依赖:GitLab CI默认如果前序阶段被规则跳过,后续阶段只要匹配自身规则就会直接运行,不会校验前序阶段状态
  • 没有排除未合入的合并请求触发的流水线:需要通过流水线来源变量过滤,仅保留分支合入后推送触发的流水线场景

修复后的deploy阶段配置

需要新增needs字段绑定build阶段的强依赖,同时调整rules规则过滤触发场景:

deploy:
    stage: deploy
    # 强依赖build_image任务成功,build被跳过/失败时deploy自动跳过
    needs: ["build_image"]
    before_script:
    - chmod 600 $SSH_KEY
    script:
    - ssh -o StrictHostKeyChecking=no -i $SSH_KEY $VPS "
        echo $REGISTRY_PASS | docker login -u $REGISTRY_USER --password-stdin &&
        cd project &&
        docker-compose pull &&
        docker-compose up -d"
    rules:
        # 仅匹配main分支的推送事件(即MR合入后的实际提交),排除未合入MR触发的流水线
        - if: '$CI_COMMIT_BRANCH == "main" && $CI_PIPELINE_SOURCE == "push"'

修正后完整可用配置

variables:
  IMAGE_TAG: project

stages:
  - build
  - deploy

build_image:
    stage: build
    image: docker:20.10.16
    services:
        - docker:20.10.16-dind
    variables:
        DOCKER_TLS_CERTDIR: "/certs"
    before_script:
        - echo $REGISTRY_PASS | docker login -u $REGISTRY_USER --password-stdin
    script:
    - |
        if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then
        tag="latest"
        echo "Running on default branch '$CI_DEFAULT_BRANCH': tag = '$tag'"
        else
        tag="$CI_COMMIT_REF_SLUG"
        echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag"
        fi
    - docker build -f .docker/Dockerfile -t $REPO_NAME:$IMAGE_TAG-$tag .
    - docker push $REPO_NAME:$IMAGE_TAG-$tag
    rules:
        - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_BRANCH == "dev"'
          changes:
            - "**/*.ts"
            - "package.json"
            - "package-lock.json"
            - ".docker/Dockerfile"
            - "resources/**/*"
            - "src/**/*"

deploy:
    stage: deploy
    needs: ["build_image"]
    before_script:
    - chmod 600 $SSH_KEY
    script:
    - ssh -o StrictHostKeyChecking=no -i $SSH_KEY $VPS "
        echo $REGISTRY_PASS | docker login -u $REGISTRY_USER --password-stdin &&
        cd project &&
        docker-compose pull &&
        docker-compose up -d"
    rules:
        - if: '$CI_COMMIT_BRANCH == "main" && $CI_PIPELINE_SOURCE == "push"'

额外说明:如果不希望dev分支的未合入MR触发build,可以在build的if条件中追加&& $CI_PIPELINE_SOURCE == "push",和deploy阶段的来源判断保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 15:57:51