Heroku CI搭配Phoenix/Elixir出现PostgreSQL角色与数据库不存在错误
解决Heroku CI + Phoenix + Elixir构建包的数据库测试错误
我来帮你搞定这个测试报错的问题——你遇到的psql: FATAL: database "u13792" does not exist和role "postgres" does not exist错误,核心原因是没有适配Heroku in-dyno PostgreSQL 的默认行为:它不会自动创建postgres角色,而且默认数据库/用户名是和dyno系统用户同名的(比如u13792)。下面是一步步的修复方案:
1. 修正app.json的测试环境配置
首先删掉手动创建postgres角色的脚本,改用Ecto自带的命令处理数据库初始化,同时让Heroku自动生成正确的DATABASE_URL:
修改app.json中的environments.test部分:
"environments": { "test": { "env": { "MIX_ENV": "test", "DATABASE_URL": { "generator": "postgres" } }, "addons": ["heroku-postgresql:in-dyno"], "scripts": { "test-setup": "mix ecto.create --quiet" } } }
DATABASE_URL: { "generator": "postgres" }:让Heroku自动生成适配in-dyno Postgres的数据库连接串,包含正确的用户名、数据库名和密码- 用
mix ecto.create --quiet代替手动psql命令:Ecto会自动处理数据库创建逻辑,避免手动操作的路径问题
2. 更新test.exs的数据库配置
不要硬编码postgres用户名、密码和数据库名,直接读取Heroku提供的DATABASE_URL,完美适配in-dyno环境:
修改config/test.exs中的Repo配置:
# Configure your database config :api, Api.Repo, url: System.get_env("DATABASE_URL"), pool: Ecto.Adapters.SQL.Sandbox, pool_size: 10
这样Ecto会直接使用Heroku生成的连接串,不需要手动指定任何硬编码的数据库凭据。
3. 调整mix.exs的测试别名
确保测试流程先创建数据库(如果不存在),再执行迁移,最后运行测试:
修改mix.exs中的aliases函数:
defp aliases do [ "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"], "ecto.reset": ["ecto.drop", "ecto.setup"], test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"], "test.local": ["ecto.create --quiet", "ecto.migrate", "test"] ] end
把默认的test别名改成先执行ecto.create --quiet,确保数据库存在后再执行迁移和测试,这样在Heroku CI环境中就能自动完成初始化。
为什么之前的配置会报错?
- 手动执行
psql -c 'CREATE ROLE postgres;'时,psql默认会尝试连接到和当前dyno用户同名的数据库(比如u13792),但此时这个数据库还没被创建,所以触发“数据库不存在”的错误 - 硬编码
postgres用户名到test.exs后,in-dyno Postgres并没有这个角色(它默认用dyno系统用户作为数据库用户),所以会出现“role postgres不存在”的连接错误
内容的提问来源于stack exchange,提问作者francob411
相关产品推荐
相关产品推荐

