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
相关产品推荐
相关产品推荐

