GitHub Actions中跨仓库测试无法访问localhost的问题求助
问题:GitHub Actions中NextJS应用与Cucumber/Playwright测试套件连接失败
背景
- 仓库A:NextJS应用
- 仓库B:Cucumber+Playwright测试套件
- 需求:仓库A的Main分支收到Pull Request时,触发GitHub Actions执行以下流程:
- 拉取PR分支头部的仓库A代码
- 安装仓库A依赖
- 构建并启动应用
- 拉取仓库B测试套件代码
- 安装测试套件依赖
- 针对运行中的应用执行测试
当前Workflow配置(第一版)
name: Automated Testing workflow on: pull_request: types: - opened branches: - 'github-actions/Test' workflow_dispatch: jobs: build-and-test: name: Build and test app runs-on: ubuntu-latest env: APP_URL: ${{ secrets.APP_URL }} USERNAME: ${{ secrets.USERNAME }} PASSWORD: ${{ secrets.PASSWORD }} ORGANISATION_NAME: ${{ secrets.ORGANISATION_NAME }} steps: - name: Checkout Git repository A uses: actions/checkout@v4 with: path: 'app' - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: 20 - name: Install Node.js dependencies working-directory: ${{ github.workspace }}/app run: npm ci - name: Run application working-directory: ${{ github.workspace }}/app run: npm run start & - name: Checkout Automated Testing suite repo uses: actions/checkout@v4 with: repository: orgname/testing-repo-B token: ${{ secrets.TOKEN }} path: 'tests' - name: Install dependencies working-directory: ${{ github.workspace }}/tests run: npm ci - name: Install playwright browsers working-directory: ${{ github.workspace }}/tests run: npx playwright install --with-deps - name: Run Testing Suite run: export APP_URL=$APP_URL && export USERNAME=$USERNAME && export PASSWORD=$PASSWORD && export ORGANISATION_NAME=$ORGANISATION_NAME && npm test working-directory: ${{ github.workspace }}/tests
错误日志
Error: a BeforeAll hook errored, process exiting: file:/home/runner/work/******/******/tests/hooks/hooks.js:36 at Runtime.runTestRunHooks (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/runtime/run_test_run_hooks.js:22:23) at async Runtime.start (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/runtime/index.js:62:9) at async runCucumber (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/api/run_cucumber.js:110:21) at async Cli.run (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/cli/index.js:56:29) at async Object.run [as default] (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/cli/run.js:29:18) { [cause]: page.goto: net::ERR_CONNECTION_REFUSED at http://*** Call log: - navigating to "***", waiting until "load" at Object.<anonymous> (/home/runner/work/******/******/tests/hooks/hooks.js:54:16) at async wrapPromiseWithTimeout (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/time.js:57:12) at async Object.run (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/user_code_runner.js:64:22) at async Runtime.runTestRunHooks (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/runtime/run_test_run_hooks.js:14:31) at async Runtime.start (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/runtime/index.js:62:9) at async runCucumber (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/api/run_cucumber.js:110:21) at async Cli.run (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/cli/index.js:56:29) at async Object.run (/home/runner/work/******/******/tests/node_modules/@cucumber/cucumber/lib/cli/run.js:29:18) { name: 'Error' } }
已尝试的方法
- 本地环境运行应用和测试套件,测试正常;
- 将APP_URL从
http://localhost:3000改为127.0.0.1,无效; - 尝试将应用作为service运行,配置如下:
name: Automated Testing workflow on: pull_request: types: - opened branches: - 'github-actions/Test' workflow_dispatch: jobs: build-and-test: name: Build and test app runs-on: ubuntu-latest env: APP_URL: ${{ secrets.APP_URL}} USERNAME: ${{ secrets.USERNAME}} PASSWORD: ${{ secrets.PASSWORD}} ORGANISATION_NAME: ${{ secrets.ORGANISATION_NAME}} container: ubuntu services: appA: image: node:20-alpine ports: - 3000:3000 steps: - name: Checkout Git repository uses: actions/checkout@v4 with: path: 'app' - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: 20 - name: Install Node.js dependencies working-directory: ${{ github.workspace }}/app run: npm ci - name: Run application working-directory: ${{ github.workspace }}/app run: npm run start:prod & - name: Checkout Automated Testing suite repo uses: actions/checkout@v4 with: repository: orgname/testing-repo-B token: ${{ secrets.TOKEN }} path: 'tests' - name: Install dependencies working-directory: ${{ github.workspace }}/tests run: npm ci - name: Install playwright browsers working-directory: ${{ github.workspace }}/tests run: export APP_URL=$APP_URL && export USERNAME=$USERNAME && export PASSWORD=$PASSWORD && export ORGANISATION_NAME=$ORGANISATION_NAME && npm test && npm test working-directory: ${{ github.workspace }}/tests
问题排查与解决方案
核心问题分析
- 应用未完全就绪就执行测试:用
npm run start &后台启动应用后,GitHub Actions会立刻执行后续步骤,此时应用可能还在编译启动中,无法接收请求。 - Service配置无效:第二版的Service仅声明了Node镜像,并未在容器内部部署和启动你的NextJS应用,实际应用仍在主Job容器中运行,Service未发挥作用。
- 环境变量传递冗余:Job级别的env已定义变量,测试步骤无需重复export。
修正后的Workflow配置
name: Automated Testing workflow on: pull_request: types: [opened, synchronize] # PR更新时也触发测试 branches: ['main'] # 匹配需求中的Main分支 workflow_dispatch: jobs: build-and-test: name: Build and test app runs-on: ubuntu-latest env: APP_URL: http://localhost:3000 # 本地地址直接声明,无需secret(特殊需求除外) USERNAME: ${{ secrets.USERNAME }} PASSWORD: ${{ secrets.PASSWORD }} ORGANISATION_NAME: ${{ secrets.ORGANISATION_NAME }} steps: - name: Checkout Git repository A uses: actions/checkout@v4 with: path: 'app' - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: 20 cache: 'npm' # 缓存依赖,加速安装 cache-dependency-path: app/package-lock.json - name: Install Node.js dependencies working-directory: ${{ github.workspace }}/app run: npm ci - name: Build NextJS app # 先构建再启动,避免启动时编译延迟 working-directory: ${{ github.workspace }}/app run: npm run build - name: Run application in background working-directory: ${{ github.workspace }}/app run: npm run start:prod & # 确保package.json中有对应脚本(一般对应next start) - name: Wait for app to be ready # 关键步骤:等待应用完全就绪 run: | timeout 120s bash -c 'until curl -s $APP_URL > /dev/null; do sleep 2; done' echo "Application is ready at $APP_URL" - name: Checkout Automated Testing suite repo uses: actions/checkout@v4 with: repository: orgname/testing-repo-B token: ${{ secrets.TOKEN }} path: 'tests' - name: Install test dependencies working-directory: ${{ github.workspace }}/tests run: npm ci - name: Install playwright browsers working-directory: ${{ github.workspace }}/tests run: npx playwright install --with-deps - name: Run Testing Suite working-directory: ${{ github.workspace }}/tests run: npm test
关键修复点说明
- 增加应用就绪等待:用
curl轮询检查应用可访问性,最多等待120秒,确保应用完全启动后再执行测试。 - 先构建再启动生产服务:NextJS的
start命令依赖预构建产物,提前build可避免启动时的编译延迟。 - 优化触发条件:将分支改为
main,并增加synchronize类型,PR更新代码时自动触发测试。 - 缓存依赖:利用Node.js Action的缓存功能,减少重复安装依赖的时间。
- 简化环境变量使用:Job级别的env会自动传递到所有步骤,无需重复export。
内容的提问来源于stack exchange,提问作者Artik Bharoliya
相关产品推荐
相关产品推荐

