一、先搞清楚失败在哪一步

当流水线执行失败时,第一步不是急着改代码,而是先看清楚报错信息。GitLab CI/CD 的 Job Logs 会明确告诉你哪一步出错了,比如是在 install 阶段依赖安装失败,还是在 test 阶段某个测试用例挂了,又或者是在 deploy 阶段权限不足。

举个例子,假设我们有一个简单的 .gitlab-ci.yml 配置,用于构建和测试一个 Node.js 项目:

stages:
  - install
  - test
  - deploy

install_dependencies:
  stage: install
  script:
    - npm install

run_tests:
  stage: test
  script:
    - npm test

deploy_to_staging:
  stage: deploy
  script:
    - echo "Deploying to staging..."
    - some_deployment_script.sh

如果 npm test 失败了,错误日志可能会显示:

Test suite failed to run
  TypeError: Cannot read property 'map' of undefined
    at /builds/project/test/example.test.js:15:25

这时候,我们就知道问题出在测试脚本的某一行代码,而不是环境配置或者部署脚本。

二、检查环境变量和依赖

很多流水线失败的原因是因为环境变量没设置,或者依赖的版本不对。比如你的项目依赖 Node.js 14,但 GitLab Runner 默认用的是 Node.js 10,那 npm install 就可能会报错。

我们可以在 .gitlab-ci.yml 里指定运行环境:

image: node:14-alpine  # 明确指定 Node.js 版本

stages:
  - install
  - test

install_dependencies:
  stage: install
  script:
    - npm install

run_tests:
  stage: test
  script:
    - npm test

如果依赖了某些敏感信息(比如数据库密码、API Key),可以通过 GitLab 的 CI/CD Variables 设置,然后在脚本里通过 $VARIABLE_NAME 调用:

deploy_to_prod:
  stage: deploy
  script:
    - echo "Using API Key: $PROD_API_KEY"
    - deploy_script.sh --key=$PROD_API_KEY

注意:敏感变量记得勾选 Masked,避免在日志里泄露。

三、利用缓存和 Artifacts 加速排查

如果每次流水线都从头安装依赖,不仅慢,还可能因为网络问题导致失败。我们可以用 cache 来缓存 node_modules

cache:
  key: $CI_COMMIT_REF_SLUG
  paths:
    - node_modules/

install_dependencies:
  stage: install
  script:
    - npm install

如果测试阶段需要用到构建产物(比如编译后的 JS 文件),可以用 artifacts 保存:

build:
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/  # 保存构建结果,供后续阶段使用

test:
  stage: test
  script:
    - npm test

这样,即使 buildtest 是在不同的 Runner 上执行,test 阶段也能拿到 dist/ 目录。

四、模拟本地环境复现问题

有时候 CI 报错,但在本地却跑得好好的。这时候可以尝试在本地模拟 CI 环境:

  1. 使用相同的 Node.js 版本

    nvm use 14  # 确保本地和 CI 的 Node.js 版本一致
    
  2. 清理依赖重新安装

    rm -rf node_modules package-lock.json
    npm install
    
  3. 检查环境变量
    如果 CI 用了某些变量(如 $DATABASE_URL),在本地也要设置:

    export DATABASE_URL="postgres://user:pass@localhost:5432/test_db"
    npm test
    

五、利用 GitLab CI 的 Retry 和 Manual 功能

有些失败是偶发的(比如网络超时),可以直接在 GitLab 界面上点击 Retry 重新运行失败的 Job。

如果是部署阶段需要人工确认,可以用 when: manual

deploy_to_prod:
  stage: deploy
  script:
    - ./deploy.sh
  when: manual  # 需要手动点击才会执行

六、查看 Runner 日志和配置

如果问题不在代码,而在 Runner 本身(比如磁盘空间不足、Docker 镜像拉取失败),可以登录 Runner 服务器查看日志:

# 查看 GitLab Runner 日志
sudo gitlab-runner logs

# 或者用 systemd 管理的 Runner
journalctl -u gitlab-runner -f

七、总结

调试 CI/CD 流水线失败的关键步骤:

  1. 看日志:先定位失败阶段和具体错误。
  2. 查环境:确保依赖版本、环境变量正确。
  3. 用缓存:减少重复安装依赖的时间。
  4. 本地复现:尽量在本地模拟 CI 环境调试。
  5. 善用重试:偶发问题可以直接 Retry。

CI/CD 流水线是自动化部署的核心,调试虽然麻烦,但掌握方法后能大幅提高效率。