Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,14 @@ jobs:
- "4.0"
- "3.4"
- "3.3"
- "jruby"
rack:
- "~> 2.0"
- "~> 3.0"
include:
- ruby: "4.0"
rack: "~> 2.0"
coverage: "true"
- ruby: "jruby"
rack: "~> 2.0"
optional: true
- ruby: "jruby"
rack: "~> 3.0"
optional: true
env:
COVERAGE: ${{ matrix.coverage }}
RACK_MATRIX_VALUE: ${{ matrix.rack || '' }}
Expand Down
1 change: 0 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ gem "hanami-devtools", github: "hanami/devtools", branch: "main"

group :test do
gem "pry"
gem "readline"
gem "rspec", "~> 3.9"
gem "ostruct", require: false
end
29 changes: 20 additions & 9 deletions lib/hanami/cli/commands/app/db/utils/database.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,18 @@ def sql
require_relative("postgres")
Postgres
},
"mysql" => -> {
require_relative("mysql")
Mysql
},
"mysql2" => -> {
require_relative("mysql")
Mysql
}
).freeze

def self.database_class(database_url)
database_scheme = URI(database_url).scheme
if database_scheme == "jdbc"
database_scheme = URI(database_url.sub("jdbc:", "")).scheme
end
database_scheme = URI(database_url.delete_prefix("jdbc:")).scheme
DATABASE_CLASS_RESOLVER[database_scheme].call
end

Expand Down Expand Up @@ -86,8 +87,20 @@ def database_url
slice.container.providers[:db].source.database_urls.fetch(gateway_name)
end

# JDBC URLs (required to connect via JRuby) nest the real URL after "jdbc:", e.g.
# "jdbc:postgresql://localhost/app", so parse that nested URL instead.
def database_uri
@database_uri ||= URI(database_url)
@database_uri ||= URI(database_url.delete_prefix("jdbc:"))
end

# JDBC drivers expect the user and password as query params, e.g.
# "jdbc:postgresql://localhost/app?user=postgres&password=secret".
def database_user
database_uri.user || database_query_params["user"]
end

def database_password
database_uri.password || database_query_params["password"]
end

def gateway
Expand Down Expand Up @@ -197,10 +210,8 @@ def schema_migrations_sql_dump

private

def database_path
database_uri.path ||
# For `jdbc:` URIs the path is exposed via the opaque component
database_uri.opaque.sub(%r{^\w+:/?}, "")
def database_query_params
@database_query_params ||= URI.decode_www_form(database_uri.query.to_s).to_h
end

def jruby?
Expand Down
4 changes: 2 additions & 2 deletions lib/hanami/cli/commands/app/db/utils/mysql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ def cli_options
[].tap { |opts|
opts << "--host=#{Shellwords.escape(database_uri.host)}" if database_uri.host
opts << "--port=#{Shellwords.escape(database_uri.port)}" if database_uri.port
opts << "--user=#{Shellwords.escape(database_uri.user)}" if database_uri.user
opts << "--user=#{Shellwords.escape(database_user)}" if database_user
}.join(" ")
end

def cli_env_vars
@cli_env_vars ||= {}.tap do |vars|
vars["MYSQL_PWD"] = database_uri.password.to_s if database_uri.password
vars["MYSQL_PWD"] = database_password.to_s if database_password
end
end
end
Expand Down
10 changes: 6 additions & 4 deletions lib/hanami/cli/commands/app/db/utils/postgres.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,12 @@ def escaped_name
end

def cli_env_vars
@cli_env_vars ||= %i[host port user password].each_with_object({}) do |field, vars|
value = database_uri.public_send(field).to_s
vars["PG#{field}".upcase] = value unless value.empty?
end
@cli_env_vars ||= {
"PGHOST" => database_uri.host,
"PGPORT" => database_uri.port,
"PGUSER" => database_user,
"PGPASSWORD" => database_password
}.transform_values(&:to_s).reject { |_, value| value.empty? }
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/hanami/cli/commands/app/db/utils/sqlite.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def name
@name ||=
begin
raw =
if database_uri.scheme == "jdbc"
if database_url.start_with?("jdbc:")
# For JDBC SQLite URIs like "jdbc:sqlite:db/app.sqlite3",
# we need to extract the path part after "jdbc:sqlite:"
# The standard URI.parse doesn't handle JDBC URIs well, so we remove the prefix manually
Expand Down
1 change: 0 additions & 1 deletion repo-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ github_org: hanami
ci:
matrix:
rack: ["~> 2.0", "~> 3.0"]
jruby: false
gemspec:
authors: ["Hanakai team"]
email: ["info@hanakai.org"]
Expand Down
26 changes: 12 additions & 14 deletions spec/integration/hanami/cli/commands/app/server_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,30 @@
require "puma"

RSpec.describe Hanami::CLI::Commands::App::Server do
subject { described_class.new }

it "starts rack server in the given environment" do
host = ENV.fetch("HANAMI_CLI_TEST_HOST", "0.0.0.0")
port = ENV.fetch("HANAMI_CLI_TEST_PORT", "2300")
app_root = File.join(__dir__, "../../../../../fixtures/test")
begin
pid = fork do
$stdout.reopen "/dev/null", "a"
$stderr.reopen "/dev/null", "a"
subject.call(
config: File.join(File.dirname(__FILE__), "../../../../../fixtures/test/config.ru"),
host: host,
port: port,
env: "staging"
)
end
# Spawn a new process rather than forking, since fork is not available on JRuby
pid = Process.spawn(
"bin/hanami", "server", "--host=#{host}", "--port=#{port}", "--env=staging",
chdir: app_root, out: File::NULL, err: File::NULL
)

response = open_uri("http://#{host}:#{port}/")

expect(response).to eq("Hello, world! (staging)")
ensure
Process.kill(:KILL, pid)
if pid
Process.kill(:KILL, pid)
Process.wait(pid)
end
end
end

def open_uri(uri, attempts = 5)
# Allow time for the new process to boot (including on JRuby)
def open_uri(uri, attempts = 30)
URI.open(uri).read # rubocop:disable Security/Open
rescue Errno::ECONNREFUSED
raise if attempts.zero?
Expand Down
17 changes: 17 additions & 0 deletions spec/support/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,23 @@ def sqlite_db_name(url, dir: nil)
jruby? && dir ? File.join(dir, url) : url
end

def postgres_url(db_suffix)
url = "#{POSTGRES_BASE_URL}#{db_suffix}"
jruby? ? jdbc_url(url, scheme: "postgresql") : url
end

def mysql_url(db_suffix)
url = "#{MYSQL_BASE_URL}#{db_suffix}"
jruby? ? jdbc_url(url, scheme: "mysql") : url
end

def jdbc_url(url, scheme:)
uri = URI(url)
# JDBC drivers expect the user and password as query params, not in the userinfo
query = URI.encode_www_form({user: uri.user, password: uri.password}.compact)
"jdbc:#{scheme}://#{uri.host}:#{uri.port}#{uri.path}?#{query}"
end

def jruby?
RUBY_ENGINE == "jruby"
end
Expand Down
8 changes: 4 additions & 4 deletions spec/unit/hanami/cli/commands/app/db/create_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def before_prepare

describe "postgres", :postgres do
before do
ENV["DATABASE_URL"] = "#{POSTGRES_BASE_URL}_app"
ENV["DATABASE_URL"] = postgres_url("_app")
end

it "creates the database" do
Expand All @@ -101,7 +101,7 @@ def before_prepare

describe "mysql", :mysql do
before do
ENV["DATABASE_URL"] = "#{MYSQL_BASE_URL}_app"
ENV["DATABASE_URL"] = mysql_url("_app")
end

it "creates the database" do
Expand Down Expand Up @@ -253,8 +253,8 @@ def before_prepare

describe "postgres", :postgres do
before do
ENV["DATABASE_URL"] = "#{POSTGRES_BASE_URL}_app"
ENV["MAIN__DATABASE_URL"] = "#{POSTGRES_BASE_URL}_main"
ENV["DATABASE_URL"] = postgres_url("_app")
ENV["MAIN__DATABASE_URL"] = postgres_url("_main")
end

it "creates each database" do
Expand Down
6 changes: 3 additions & 3 deletions spec/unit/hanami/cli/commands/app/db/drop_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,8 @@ def before_prepare

describe "postgres", :postgres do
before do
ENV["DATABASE_URL"] = "#{POSTGRES_BASE_URL}_app"
ENV["MAIN__DATABASE_URL"] = "#{POSTGRES_BASE_URL}_main"
ENV["DATABASE_URL"] = postgres_url("_app")
ENV["MAIN__DATABASE_URL"] = postgres_url("_main")
end

it "drops each database" do
Expand Down Expand Up @@ -427,7 +427,7 @@ def before_prepare

describe "mysql", :mysql do
before do
ENV["DATABASE_URL"] = "#{MYSQL_BASE_URL}_app"
ENV["DATABASE_URL"] = mysql_url("_app")
end

it "drops the database" do
Expand Down
4 changes: 2 additions & 2 deletions spec/unit/hanami/cli/commands/app/db/migrate_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,8 @@ def before_prepare

describe "postgres", :postgres do
before do
ENV["DATABASE_URL"] = "#{POSTGRES_BASE_URL}_app"
ENV["MAIN__DATABASE_URL"] = "#{POSTGRES_BASE_URL}_main"
ENV["DATABASE_URL"] = postgres_url("_app")
ENV["MAIN__DATABASE_URL"] = postgres_url("_main")
db_create
end

Expand Down
4 changes: 2 additions & 2 deletions spec/unit/hanami/cli/commands/app/db/prepare_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ class Comments < Hanami::DB::Relation

describe "postgres", :postgres do
before do
ENV["DATABASE_URL"] = "#{POSTGRES_BASE_URL}_app"
ENV["MAIN__DATABASE_URL"] = "#{POSTGRES_BASE_URL}_main"
ENV["DATABASE_URL"] = postgres_url("_app")
ENV["MAIN__DATABASE_URL"] = postgres_url("_main")
end

context "from scratch, with structure dump and seeds" do
Expand Down
20 changes: 10 additions & 10 deletions spec/unit/hanami/cli/commands/app/db/rollback_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,8 @@ class App < Hanami::App

describe "postgres", :postgres do
before do
ENV["DATABASE_URL"] = "#{POSTGRES_BASE_URL}_app"
ENV["MAIN__DATABASE_URL"] = "#{POSTGRES_BASE_URL}_main"
ENV["DATABASE_URL"] = postgres_url("_app")
ENV["MAIN__DATABASE_URL"] = postgres_url("_main")
end

context "single database" do
Expand Down Expand Up @@ -394,9 +394,9 @@ def before_prepare_gateways
end

before do
ENV["DATABASE_URL"] = "#{POSTGRES_BASE_URL}_app"
ENV["DATABASE_URL__EXTRA"] = "#{POSTGRES_BASE_URL}_extra"
ENV["DATABASE_URL__SUPER"] = "#{POSTGRES_BASE_URL}_super"
ENV["DATABASE_URL"] = postgres_url("_app")
ENV["DATABASE_URL__EXTRA"] = postgres_url("_extra")
ENV["DATABASE_URL__SUPER"] = postgres_url("_super")

with_directory(@dir = make_tmp_directory) do
write "config/app.rb", <<~RUBY
Expand Down Expand Up @@ -424,8 +424,8 @@ class App < Hanami::App

describe "mysql", :mysql do
before do
ENV["DATABASE_URL"] = "#{MYSQL_BASE_URL}_app"
ENV["MAIN__DATABASE_URL"] = "#{MYSQL_BASE_URL}_main"
ENV["DATABASE_URL"] = mysql_url("_app")
ENV["MAIN__DATABASE_URL"] = mysql_url("_main")
end

context "single database" do
Expand Down Expand Up @@ -467,9 +467,9 @@ def before_prepare_gateways
end

before do
ENV["DATABASE_URL"] = "#{MYSQL_BASE_URL}_app"
ENV["DATABASE_URL__EXTRA"] = "#{MYSQL_BASE_URL}_extra"
ENV["DATABASE_URL__SUPER"] = "#{MYSQL_BASE_URL}_super"
ENV["DATABASE_URL"] = mysql_url("_app")
ENV["DATABASE_URL__EXTRA"] = mysql_url("_extra")
ENV["DATABASE_URL__SUPER"] = mysql_url("_super")

with_directory(@dir = make_tmp_directory) do
write "config/app.rb", <<~RUBY
Expand Down
6 changes: 3 additions & 3 deletions spec/unit/hanami/cli/commands/app/db/structure/dump_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,8 @@ def before_prepare

describe "postgres", :postgres do
before do
ENV["DATABASE_URL"] = "#{POSTGRES_BASE_URL}_app"
ENV["MAIN__DATABASE_URL"] = "#{POSTGRES_BASE_URL}_main"
ENV["DATABASE_URL"] = postgres_url("_app")
ENV["MAIN__DATABASE_URL"] = postgres_url("_main")
db_migrate
end

Expand Down Expand Up @@ -299,7 +299,7 @@ def before_prepare

describe "mysql", :mysql do
before do
ENV["DATABASE_URL"] = "#{MYSQL_BASE_URL}_app"
ENV["DATABASE_URL"] = mysql_url("_app")
db_migrate
end

Expand Down
6 changes: 3 additions & 3 deletions spec/unit/hanami/cli/commands/app/db/structure/load_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,8 @@ def before_prepare

describe "postgres", :postgres do
before do
ENV["DATABASE_URL"] = "#{POSTGRES_BASE_URL}_app"
ENV["MAIN__DATABASE_URL"] = "#{POSTGRES_BASE_URL}_main"
ENV["DATABASE_URL"] = postgres_url("_app")
ENV["MAIN__DATABASE_URL"] = postgres_url("_main")
db_structure_dump
end

Expand Down Expand Up @@ -249,7 +249,7 @@ def before_prepare

describe "mysql", :mysql do
before do
ENV["DATABASE_URL"] = "#{MYSQL_BASE_URL}_app"
ENV["DATABASE_URL"] = mysql_url("_app")
db_structure_dump
end

Expand Down
Loading