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

GitHub Actions中Prisma连接PostgreSQL偶发P1001错误求助

偶发GitHub Actions集成测试失败:无法连接PostgreSQL数据库

问题现象

在GitHub Actions中通过Prisma执行集成测试时,偶尔会出现数据库连接失败的错误,重启1-2次后恢复正常。错误信息如下:

Run npm run test:migrate

> fictadvisor-api@0.0.1 test:migrate
> dotenv -e .testing.env -- prisma migrate deploy

Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "postgres", schema "public" at "localhost:5432"

Error: P1001: Can't reach database server at localhost:5432

Please make sure your database server is running at localhost:5432.
Error: Process completed with exit code 1.

已尝试在DATABASE_URL中设置connection_timeout,但无效果。

当前配置

GitHub Actions集成测试步骤

integration-test:
  runs-on: ubuntu-latest
  steps:
    - name: Checkout
      uses: actions/checkout@v3
    - name: Install Node and dependencies
      uses: ./.github/actions/install
    - name: Start PostgreSQL Database
      run: |
        docker-compose up -d
    - name: Start migration
      run: npm run test:migrate
    - name: Start generating
      run: npm run test:generate
    - name: Start seeding
      run: npm run test:seed
    - name: Run integration tests
      run: npm run test:integration

docker-compose.yml

version: '3'

services:
  db:
    image: postgres:15
    container_name: testing-db
    restart: always
    ports:
      - "5432:5432"
    environment:
      POSTGRES_PASSWORD: postgres

package.json脚本配置

"scripts": {
    "prebuild": "rimraf dist",
    "build": "nest build",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "nest start",
    "start:dev": "dotenv -e .development.env -- cross-env NODE_ENV=development nest start --watch",
    "start:debug": "nest start --debug --watch",
    "start:prod": "cross-env NODE_ENV=production node dist/main",
    "lint": "eslint . --ext .ts",
    "lint:fix": "eslint . --ext .ts --fix",
    "test:unit": "cross-env NODE_ENV=testing dotenv -e .testing.env -- jest -c jest.unit.config.json",
    "test:integration": "cross-env NODE_ENV=testing dotenv -e .testing.env -- jest -c jest.integration.config.json -i",
    "test:migrate": "dotenv -e .testing.env -- prisma migrate deploy",
    "test:seed": "dotenv -e .testing.env -- prisma db seed",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json",
    "test:generate": "dotenv -e .testing.env -- prisma generate",
    "integration:full": "docker compose up -d && yarn test:migrate && yarn test:seed && yarn test:integration && docker compose down",
    "generate:dev": "dotenv -e .development.env -- npx prisma generate",
    "migrate:sql": "dotenv -e .development.env -- npx prisma migrate dev --create-only --name",
    "migrate:dev": "dotenv -e .development.env -- npx prisma migrate dev"
  },

.testing.env

SECRET=testing-secret
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres
TIME_DIFFERENCE=3
TZ=UTC

package.json依赖项

"dependencies": {
    "@nestjs-modules/mailer": "^1.8.1",
    "@nestjs/common": "^9.2.1",
    "@nestjs/config": "^2.2.0",
    "@nestjs/core": "^9.2.1",
    "@nestjs/jwt": "^10.0.3",
    "@nestjs/passport": "^9.0.0",
    "@nestjs/platform-express": "^9.2.1",
    "@nestjs/schedule": "^3.0.1",
    "@nestjs/swagger": "^6.3.0",
    "@nestjs/typeorm": "^9.0.1",
    "@prisma/client": "4.16.2",
    "@types/bcrypt": "^5.0.0",
    "@types/jsdom": "^21.1.0",
    "@types/nodemailer": "^6.4.7",
    "@types/passport-local": "^1.0.34",
    "axios": "^1.2.1",
    "bcrypt": "^5.1.0",
    "class-transformer": "^0.5.1",
    "class-validator": "^0.14.0",
    "cross-env": "^7.0.3",
    "docxtemplater": "^3.37.12",
    "dotenv-cli": "^7.2.1",
    "handlebars": "^4.7.7",
    "jsdom": "^22.0.0",
    "nodemailer": "^6.9.0",
    "passport": "^0.6.0",
    "passport-jwt": "^4.0.0",
    "passport-local": "^1.0.0",
    "pizzip": "^3.1.4",
    "prisma": "4.16.2",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^5.0.1",
    "rxjs": "^7.6.0",
    "uuid": "^9.0.0"
  },
  "devDependencies": {
    "@nestjs/cli": "^9.1.5",
    "@nestjs/schematics": "^9.0.3",
    "@nestjs/testing": "^9.2.1",
    "@types/cron": "^2.0.1",
    "@types/dateformat": "^5.0.0",
    "@types/express": "^4.17.15",
    "@types/jest": "^29.5.1",
    "@types/multer": "^1.4.7",
    "@types/node": "^20.2.5",
    "@types/passport-jwt": "^3.0.8",
    "@types/supertest": "^2.0.12",
    "@types/uuid": "^9.0.0",
    "@typescript-eslint/eslint-plugin": "5.59.7",
    "@typescript-eslint/parser": "5.59.7",
    "eslint": "^8.32.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-import": "^2.26.0",
    "jest": "^29.5.0",
    "prettier": "^2.8.1",
    "supertest": "^6.3.3",
    "ts-jest": "29.1.0",
    "ts-loader": "^9.4.2",
    "ts-node": "10.9.1",
    "tsconfig-paths": "^4.1.1",
    "typescript": "5.0.4"
  }

解决方案

1. 等待数据库完全启动后再执行迁移

问题根源是docker-compose up -d启动容器后,PostgreSQL可能还未完成初始化就开始执行迁移脚本。添加等待逻辑确认数据库可连接:

修改GitHub Actions中的数据库启动步骤:

- name: Install PostgreSQL client
  run: sudo apt-get update && sudo apt-get install -y postgresql-client

- name: Start PostgreSQL Database and wait for it to be ready
  run: |
    docker-compose up -d
    # 循环检查数据库是否就绪
    until pg_isready -h localhost -p 5432 -U postgres; do
      echo "Waiting for database to be ready..."
      sleep 2
    done

2. 增强数据库连接配置

在DATABASE_URL中添加连接超时和重试相关参数:

DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres?connect_timeout=10&pool_timeout=10&connection_limit=10

同时在Prisma schema中配置连接池参数:

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
  pool {
    min = 1
    max = 10
    create_timeout = 10s
    idle_timeout = 30s
    acquire_timeout = 10s
  }
}

3. 使用GitHub官方PostgreSQL Action替代Docker Compose

官方Action会自动处理数据库初始化等待,稳定性更高:

- name: Start PostgreSQL
  uses: actions/setup-postgres@v2
  with:
    postgres-version: '15'
    password: postgres
    database: postgres

替换后无需再使用Docker Compose,直接使用该Action提供的数据库即可。

4. 给迁移步骤添加重试逻辑

在GitHub Actions中对迁移步骤设置重试,避免偶发连接失败:

- name: Start migration with retries
  run: npm run test:migrate
  continue-on-error: true
  id: migrate

- name: Retry migration if failed
  run: npm run test:migrate
  if: steps.migrate.outcome == 'failure'

总结

最直接有效的方案是添加数据库就绪等待逻辑,确保PostgreSQL完全初始化后再执行迁移脚本。如果追求更高稳定性,推荐替换为官方PostgreSQL Action。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 06:17:06