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

GitLab流水线中Cypress测试完成后无法自动退出问题排查

GitLab流水线Cypress测试完成后任务无法自动退出的解决方法

问题场景

使用cypress/included:12.8.1镜像在GitLab流水线中运行Cypress测试,已通过设置entrypoint: [""]解决默认入口点自动执行cypress run找不到配置文件的问题。但测试完成后,流水线任务无法自动退出,最终因1小时超时失败。调试日志显示Cypress已准备以0码退出,但后台运行的Next服务器进程未终止,导致任务无法结束。

当前GitLab CI配置如下:

---
cypress tests:
  image: 
    name: cypress/included:12.8.1
    entrypoint: [""]
  stage: e2e-tests
  interruptible: true
  dependencies: []
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - .npm
      - cache/Cypress
  rules:
    - exists:
      - cypress.config.js
  artifacts:
    # Store cypress screenshots as artifacts on job failure only
    when: on_failure
    expire_in: 1 day
    paths:
      - ${CI_PROJECT_DIR}/cypress/screenshots
      - ${CI_PROJECT_DIR}/cypress/videos
  script:
    - npm ci
    - npm run build --omit=dev
    - npm run start &
    - DEBUG=cypress:server* npx cypress run --headless --config-file cypress.config.js -c video=false

问题原因

通过npm run start &将Next服务器放到后台运行后,测试完成时该进程未被终止。GitLab CI会等待所有子进程结束才会终止任务,因此导致超时。

解决方案

方案1:记录服务器PID并在测试后终止进程

修改脚本,启动服务器时记录其PID,Cypress测试完成后手动杀死该进程:

script:
  - npm ci
  - npm run build --omit=dev
  # 启动服务器并记录PID到文件
  - npm run start & echo $! > next.pid
  # 等待服务器启动完成(可根据实际情况调整等待时间)
  - sleep 30
  - DEBUG=cypress:server* npx cypress run --headless --config-file cypress.config.js -c video=false
  # 杀死后台的Next服务器进程,添加|| true避免进程不存在时报错
  - kill $(cat next.pid) || true

方案2:使用wait-on等待服务器就绪,精准终止进程

先安装wait-on工具,等待服务器指定端口就绪后再运行测试,测试结束后杀死Next相关进程:

script:
  - npm ci
  - npm install -g wait-on
  - npm run build --omit=dev
  - npm run start &
  # 等待Next默认3000端口就绪
  - wait-on http://localhost:3000
  - DEBUG=cypress:server* npx cypress run --headless --config-file cypress.config.js -c video=false
  # 杀死所有与next start相关的进程
  - pkill -f "next start" || true

方案3:让Cypress自动管理服务器生命周期

修改cypress.config.js,通过setupNodeEvents配置Cypress在测试前后启动和关闭服务器,无需在CI脚本中手动处理:

// cypress.config.js
const { defineConfig } = require('cypress')
const next = require('next')

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      on('before:run', async () => {
        // 启动生产模式的Next服务(已执行build)
        const app = next({ dev: false })
        await app.prepare()
        const handle = app.getRequestHandler()
        config.server = require('http').createServer((req, res) => {
          handle(req, res)
        })
        config.server.listen(3000)
        return config
      })

      on('after:run', (config) => {
        // 测试完成后关闭服务器
        config.server.close()
      })
    },
    baseUrl: 'http://localhost:3000'
  }
})

对应CI脚本可简化为:

script:
  - npm ci
  - npm run build --omit=dev
  - DEBUG=cypress:server* npx cypress run --headless --config-file cypress.config.js -c video=false

推荐选择

优先选择方案1或方案2,配置简单且无需修改Cypress核心配置;若希望更优雅地管理服务器生命周期,可使用方案3。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 08:34:54