From 2b10ff822eda2403e47e73686c00ddb8a294c385 Mon Sep 17 00:00:00 2001 From: Philip Arndt Date: Mon, 5 Oct 2026 18:29:11 +1300 Subject: [PATCH 1/6] Use Hanami::DB::DatabaseURL in db command utils Replace the db utils' own JDBC URL handling and scheme aliases with the shared helper from hanami-db (hanami/hanami-db#25). hanami-db is required only when resolving a database class, rather than at the top of utils/database.rb, since every app command loads that file, including in apps that do not use hanami-db (an optional dependency of hanami-cli). --- .../cli/commands/app/db/utils/database.rb | 38 +++++++++---------- .../cli/commands/app/db/utils/sqlite.rb | 2 +- .../commands/app/db/utils/database_spec.rb | 27 +++++++++++++ 3 files changed, 45 insertions(+), 22 deletions(-) create mode 100644 spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb diff --git a/lib/hanami/cli/commands/app/db/utils/database.rb b/lib/hanami/cli/commands/app/db/utils/database.rb index d4c11750..0bc9cb33 100644 --- a/lib/hanami/cli/commands/app/db/utils/database.rb +++ b/lib/hanami/cli/commands/app/db/utils/database.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true -require "uri" require "delegate" module Hanami @@ -23,34 +22,31 @@ def sql end end - DATABASE_CLASS_RESOLVER = Hash.new { |_, key| - raise "#{key} is not a supported db scheme" - }.update( - "sqlite" => -> { + DATABASE_CLASS_RESOLVER = { + sqlite: -> { require_relative("sqlite") Sqlite }, - "postgres" => -> { + postgres: -> { require_relative("postgres") Postgres }, - "postgresql" => -> { - require_relative("postgres") - Postgres - }, - "mysql" => -> { - require_relative("mysql") - Mysql - }, - "mysql2" => -> { + mysql: -> { require_relative("mysql") Mysql } - ).freeze + }.freeze def self.database_class(database_url) - database_scheme = URI(database_url.delete_prefix("jdbc:")).scheme - DATABASE_CLASS_RESOLVER[database_scheme].call + # Required here rather than at the top of this file, since every app command loads + # this file, including in apps that do not use hanami-db. + require "hanami-db" + + adapter = Hanami::DB::DatabaseURL.adapter(database_url) + + DATABASE_CLASS_RESOLVER.fetch(adapter) { + raise "#{Hanami::DB::DatabaseURL.uri(database_url).scheme} is not a supported db scheme" + }.call end def self.from_slice(slice:, system_call:) @@ -87,10 +83,10 @@ 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. + # Parses the URL nested in JDBC URLs (required to connect via JRuby), e.g. + # "jdbc:postgresql://localhost/app". def database_uri - @database_uri ||= URI(database_url.delete_prefix("jdbc:")) + @database_uri ||= Hanami::DB::DatabaseURL.uri(database_url) end # JDBC drivers expect the user and password as query params, e.g. diff --git a/lib/hanami/cli/commands/app/db/utils/sqlite.rb b/lib/hanami/cli/commands/app/db/utils/sqlite.rb index 11d7885c..ed1df63c 100644 --- a/lib/hanami/cli/commands/app/db/utils/sqlite.rb +++ b/lib/hanami/cli/commands/app/db/utils/sqlite.rb @@ -72,7 +72,7 @@ def name @name ||= begin raw = - if database_url.start_with?("jdbc:") + if Hanami::DB::DatabaseURL.jdbc?(database_url) # 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 diff --git a/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb b/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb new file mode 100644 index 00000000..2e8401a6 --- /dev/null +++ b/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require "hanami/cli/commands/app/db/utils/database" + +RSpec.describe Hanami::CLI::Commands::App::DB::Utils::Database do + describe ".database_class" do + { + "sqlite://db/app.sqlite3" => "Sqlite", + "jdbc:sqlite:db/app.sqlite3" => "Sqlite", + "postgres://localhost/app" => "Postgres", + "postgresql://localhost/app" => "Postgres", + "jdbc:postgresql://localhost/app" => "Postgres", + "mysql://localhost/app" => "Mysql", + "mysql2://localhost/app" => "Mysql", + "jdbc:mysql://localhost/app" => "Mysql" + }.each do |url, class_name| + it "returns #{class_name} for #{url}" do + expect(described_class.database_class(url).name).to eq "Hanami::CLI::Commands::App::DB::Utils::#{class_name}" + end + end + + it "raises an error for unsupported schemes, without including the URL's credentials" do + expect { described_class.database_class("oracle://user:secret@localhost/app") } + .to raise_error(RuntimeError, "oracle is not a supported db scheme") + end + end +end From eb3e95d04abd0a826d59354abb57b1b9e3ed6ca7 Mon Sep 17 00:00:00 2001 From: Philip Arndt Date: Mon, 5 Oct 2026 18:32:57 +1300 Subject: [PATCH 2/6] Raise clearer errors for unsupported or invalid database URLs Raise the existing (previously unused) UnsupportedDatabaseSchemeError for unsupported schemes, and a new InvalidDatabaseURLError for URLs that cannot be parsed, rather than a RuntimeError or URI::InvalidURIError. Neither includes the URL in its message, nor carries the URI error as its cause, since the URL may contain credentials. --- CHANGELOG.md | 2 ++ .../cli/commands/app/db/utils/database.rb | 27 ++++++++++++++++++- lib/hanami/cli/errors.rb | 13 +++++++++ .../commands/app/db/utils/database_spec.rb | 26 +++++++++++++++++- 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10e9f102..728f2789 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ and this project adheres to [Break Versioning](https://www.taoensso.com/break-ve ### Changed - Print clearer errors when Postgres CLI commands fail. (@mddelk in #437) +- Require hanami-db 3.1 or later for `hanami db` commands, using its new `Hanami::DB::DatabaseURL` to recognise database URLs, including JRuby's JDBC URLs. (@parndt) +- Raise `Hanami::CLI::UnsupportedDatabaseSchemeError` from `hanami db` commands for unsupported database URL schemes, and the new `Hanami::CLI::InvalidDatabaseURLError` for database URLs that cannot be parsed, rather than a `RuntimeError` or `URI::InvalidURIError`. Neither error includes the URL, since it may contain credentials. (@parndt) - Ignore SQLite's `-wal`, `-shm` and `-journal` files in the `.gitignore` generated by `hanami new`, by widening `db/*.sqlite` to `db/*.sqlite*`. (@cllns in #451) - Use Dry CLI 2.0 (@timriley) - Commands now use the I/O streams given by Dry CLI 2.0's `Dry::CLI::Command`, and take `stdout:`, `stderr:` and `stdin:` in place of `out:` and `err:`. (@timriley) diff --git a/lib/hanami/cli/commands/app/db/utils/database.rb b/lib/hanami/cli/commands/app/db/utils/database.rb index 0bc9cb33..43c5be0f 100644 --- a/lib/hanami/cli/commands/app/db/utils/database.rb +++ b/lib/hanami/cli/commands/app/db/utils/database.rb @@ -37,6 +37,10 @@ def sql } }.freeze + # Matches a URL's scheme, including any JDBC subprotocol, e.g. "jdbc:sqlserver" + DATABASE_SCHEME_MATCHER = /\A(?:jdbc:)?[a-z][a-z0-9+.-]*(?=:)/i + private_constant :DATABASE_SCHEME_MATCHER + def self.database_class(database_url) # Required here rather than at the top of this file, since every app command loads # this file, including in apps that do not use hanami-db. @@ -45,10 +49,31 @@ def self.database_class(database_url) adapter = Hanami::DB::DatabaseURL.adapter(database_url) DATABASE_CLASS_RESOLVER.fetch(adapter) { - raise "#{Hanami::DB::DatabaseURL.uri(database_url).scheme} is not a supported db scheme" + scheme = database_scheme(database_url) + + raise Hanami::CLI::InvalidDatabaseURLError.new(scheme) unless parseable?(database_url) + + raise Hanami::CLI::UnsupportedDatabaseSchemeError.new(scheme) }.call end + # Returns false when the URL cannot be parsed. Avoids raising from a `rescue`, since + # the URI error (whose message includes the URL) would become the new error's cause. + def self.parseable?(database_url) + Hanami::DB::DatabaseURL.uri(database_url) + true + rescue URI::Error + false + end + private_class_method :parseable? + + # Returns the URL's scheme for use in error messages. Unlike parsing the URL, this + # cannot fail, and never exposes the credentials the URL may contain. + def self.database_scheme(database_url) + database_url.to_s[DATABASE_SCHEME_MATCHER] || "(none)" + end + private_class_method :database_scheme + def self.from_slice(slice:, system_call:) provider = slice.container.providers[:db] raise "No :db provider for #{slice}" unless provider diff --git a/lib/hanami/cli/errors.rb b/lib/hanami/cli/errors.rb index 46c26485..d961ec26 100644 --- a/lib/hanami/cli/errors.rb +++ b/lib/hanami/cli/errors.rb @@ -119,6 +119,19 @@ def initialize(scheme) end end + # Does not include the URL itself, since it may contain credentials. + # + # @since 3.1.0 + # @api public + class InvalidDatabaseURLError < Error + def initialize(scheme) + super( + "`#{scheme}' database URL could not be parsed. " \ + "Check it for characters that need escaping, such as in the password" + ) + end + end + # rubocop:disable Layout/LineLength # @since 2.2.0 # @api public diff --git a/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb b/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb index 2e8401a6..2339e126 100644 --- a/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb +++ b/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb @@ -21,7 +21,31 @@ it "raises an error for unsupported schemes, without including the URL's credentials" do expect { described_class.database_class("oracle://user:secret@localhost/app") } - .to raise_error(RuntimeError, "oracle is not a supported db scheme") + .to raise_error(Hanami::CLI::UnsupportedDatabaseSchemeError, "`oracle' is not a supported db scheme") + end + + it "includes the JDBC subprotocol in the error for unsupported JDBC URLs" do + expect { described_class.database_class("jdbc:sqlserver://localhost;user=sa;password=secret") } + .to raise_error(Hanami::CLI::UnsupportedDatabaseSchemeError, "`jdbc:sqlserver' is not a supported db scheme") + end + + it "raises an error for unsupported JDBC subprotocols" do + expect { described_class.database_class("jdbc:postgres://localhost/app") } + .to raise_error(Hanami::CLI::UnsupportedDatabaseSchemeError, "`jdbc:postgres' is not a supported db scheme") + end + + it "raises an error for URLs that cannot be parsed, without including the URL's credentials" do + expect { described_class.database_class("postgres://user:se cret@localhost/app") } + .to raise_error(Hanami::CLI::InvalidDatabaseURLError) { |error| + expect(error.message).to start_with "`postgres' database URL could not be parsed" + expect(error.message).not_to include "cret" + expect(error.cause).to be_nil + } + end + + it "raises an error for URLs without a scheme" do + expect { described_class.database_class("db/app.sqlite3") } + .to raise_error(Hanami::CLI::UnsupportedDatabaseSchemeError, "`(none)' is not a supported db scheme") end end end From 9871c5f86c9c7f3538449b3a050b0b598581e62e Mon Sep 17 00:00:00 2001 From: Philip Arndt Date: Mon, 5 Oct 2026 18:34:41 +1300 Subject: [PATCH 3/6] Raise a clear error when hanami-db is too old hanami-db is an optional dependency, so hanami-cli's gemspec cannot require a minimum version of it. Apps upgrading hanami-cli while keeping an older hanami-db would otherwise hit a NameError for Hanami::DB::DatabaseURL when running `hanami db` commands. This matches the equivalent check in hanami's db provider. --- CHANGELOG.md | 2 +- .../cli/commands/app/db/utils/database.rb | 21 ++++++++++++++++--- lib/hanami/cli/errors.rb | 11 ++++++++++ .../commands/app/db/utils/database_spec.rb | 10 +++++++++ 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 728f2789..d261f78b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ and this project adheres to [Break Versioning](https://www.taoensso.com/break-ve ### Changed - Print clearer errors when Postgres CLI commands fail. (@mddelk in #437) -- Require hanami-db 3.1 or later for `hanami db` commands, using its new `Hanami::DB::DatabaseURL` to recognise database URLs, including JRuby's JDBC URLs. (@parndt) +- Require hanami-db 3.1 or later for `hanami db` commands, using its new `Hanami::DB::DatabaseURL` to recognise database URLs, including JRuby's JDBC URLs. If an older hanami-db is installed, these commands raise `Hanami::CLI::HanamiDBVersionError`, explaining how to upgrade. (@parndt) - Raise `Hanami::CLI::UnsupportedDatabaseSchemeError` from `hanami db` commands for unsupported database URL schemes, and the new `Hanami::CLI::InvalidDatabaseURLError` for database URLs that cannot be parsed, rather than a `RuntimeError` or `URI::InvalidURIError`. Neither error includes the URL, since it may contain credentials. (@parndt) - Ignore SQLite's `-wal`, `-shm` and `-journal` files in the `.gitignore` generated by `hanami new`, by widening `db/*.sqlite` to `db/*.sqlite*`. (@cllns in #451) - Use Dry CLI 2.0 (@timriley) diff --git a/lib/hanami/cli/commands/app/db/utils/database.rb b/lib/hanami/cli/commands/app/db/utils/database.rb index 43c5be0f..10cb8f13 100644 --- a/lib/hanami/cli/commands/app/db/utils/database.rb +++ b/lib/hanami/cli/commands/app/db/utils/database.rb @@ -41,10 +41,15 @@ def sql DATABASE_SCHEME_MATCHER = /\A(?:jdbc:)?[a-z][a-z0-9+.-]*(?=:)/i private_constant :DATABASE_SCHEME_MATCHER + # Minimum hanami-db version providing the Hanami::DB::DatabaseURL helpers used here. + # + # hanami-db is an optional dependency, so hanami-cli's gemspec cannot require it. This + # means apps can upgrade hanami-cli while keeping an older hanami-db. + MINIMUM_HANAMI_DB_VERSION = "3.1.0" + private_constant :MINIMUM_HANAMI_DB_VERSION + def self.database_class(database_url) - # Required here rather than at the top of this file, since every app command loads - # this file, including in apps that do not use hanami-db. - require "hanami-db" + ensure_hanami_db_version adapter = Hanami::DB::DatabaseURL.adapter(database_url) @@ -57,6 +62,16 @@ def self.database_class(database_url) }.call end + # Requires hanami-db here rather than at the top of this file, since every app command + # loads this file, including in apps that do not use hanami-db. + def self.ensure_hanami_db_version + require "hanami-db" + return if defined?(Hanami::DB::DatabaseURL) + + raise Hanami::CLI::HanamiDBVersionError.new(MINIMUM_HANAMI_DB_VERSION, Hanami::DB::VERSION) + end + private_class_method :ensure_hanami_db_version + # Returns false when the URL cannot be parsed. Avoids raising from a `rescue`, since # the URI error (whose message includes the URL) would become the new error's cause. def self.parseable?(database_url) diff --git a/lib/hanami/cli/errors.rb b/lib/hanami/cli/errors.rb index d961ec26..69377d91 100644 --- a/lib/hanami/cli/errors.rb +++ b/lib/hanami/cli/errors.rb @@ -119,6 +119,17 @@ def initialize(scheme) end end + # @since 3.1.0 + # @api public + class HanamiDBVersionError < Error + def initialize(minimum_version, installed_version) + super( + "hanami-cli #{Hanami::CLI::VERSION} requires hanami-db #{minimum_version} or later, " \ + "but #{installed_version} is installed. Please run `bundle update hanami-db`." + ) + end + end + # Does not include the URL itself, since it may contain credentials. # # @since 3.1.0 diff --git a/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb b/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb index 2339e126..68248c66 100644 --- a/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb +++ b/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb @@ -19,6 +19,16 @@ end end + it "raises an error when the installed hanami-db is too old" do + hide_const "Hanami::DB::DatabaseURL" + + expect { described_class.database_class("postgres://localhost/app") } + .to raise_error(Hanami::CLI::HanamiDBVersionError) { |error| + expect(error.message).to include "requires hanami-db 3.1.0 or later, but #{Hanami::DB::VERSION} is installed" + expect(error.message).to include "bundle update hanami-db" + } + end + it "raises an error for unsupported schemes, without including the URL's credentials" do expect { described_class.database_class("oracle://user:secret@localhost/app") } .to raise_error(Hanami::CLI::UnsupportedDatabaseSchemeError, "`oracle' is not a supported db scheme") From 3a1dfe18f6f0133266c82100923cb4f4613efdf4 Mon Sep 17 00:00:00 2001 From: Philip Arndt Date: Tue, 3 Nov 2026 11:22:48 +1300 Subject: [PATCH 4/6] Use hanami-cli's hanami-db in the database E2E app The E2E app is generated with released gems, so it installs the latest hanami-db from RubyGems. When hanami-cli depends on unreleased hanami-db changes (such as Hanami::DB::DatabaseURL), every E2E job fails with hanami-cli's "requires hanami-db 3.1.0 or later" error. Copy the hanami-db line from hanami-cli's own Gemfile into the app's Gemfile, so the app is always tested against the same hanami-db as hanami-cli's specs. This follows any temporary branch pointer and needs no change once it is reverted. --- .github/workflows/database-e2e.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/database-e2e.sh b/.github/workflows/database-e2e.sh index c470f880..b531412f 100755 --- a/.github/workflows/database-e2e.sh +++ b/.github/workflows/database-e2e.sh @@ -35,6 +35,11 @@ grep -q 'gem "hanami-cli", path:' testapp/Gemfile sed -i 's|^\([[:space:]]*\)gem "hanami-reloader".*|\1gem "hanami-reloader", github: "hanami/hanami-reloader", branch: "main"|' testapp/Gemfile echo 'gem "dry-cli", github: "dry-rb/dry-cli", branch: "main"' >> testapp/Gemfile +# Use the same hanami-db as hanami-cli's own Gemfile, since hanami-cli may need unreleased hanami-db changes +HANAMI_DB_GEM=$(grep '^gem "hanami-db"' "$GITHUB_WORKSPACE/Gemfile") +sed -i "s|^\([[:space:]]*\)gem \"hanami-db\".*|\1$HANAMI_DB_GEM|" testapp/Gemfile +grep -qF "$HANAMI_DB_GEM" testapp/Gemfile + if [ "$JRUBY" = "true" ]; then case "$E2E_DATABASE_FLAG" in sqlite) From 87415daaacd49ad83c98cf5100c5d565c068ce75 Mon Sep 17 00:00:00 2001 From: Philip Arndt Date: Wed, 4 Nov 2026 11:50:29 +1300 Subject: [PATCH 5/6] Remove the hanami-db version check from db commands Hanami gems are designed to work together only at the same major.minor version, which upgrade notes and newly generated Gemfiles make clear. Checking for a minimum hanami-db here adds work we're not doing anywhere else, so drop it, along with HanamiDBVersionError, for now. A standard way to handle this can come with the extensions API. This reverts "Raise a clear error when hanami-db is too old" and removes the CHANGELOG entry about requiring hanami-db 3.1, matching the same change in hanami. The database E2E script still uses hanami-cli's own hanami-db, since without it the generated app would get a NameError for Hanami::DB::DatabaseURL until hanami-db 3.1 is released. --- CHANGELOG.md | 1 - .../cli/commands/app/db/utils/database.rb | 21 +++---------------- lib/hanami/cli/errors.rb | 11 ---------- .../commands/app/db/utils/database_spec.rb | 10 --------- 4 files changed, 3 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d261f78b..a32f6b4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,6 @@ and this project adheres to [Break Versioning](https://www.taoensso.com/break-ve ### Changed - Print clearer errors when Postgres CLI commands fail. (@mddelk in #437) -- Require hanami-db 3.1 or later for `hanami db` commands, using its new `Hanami::DB::DatabaseURL` to recognise database URLs, including JRuby's JDBC URLs. If an older hanami-db is installed, these commands raise `Hanami::CLI::HanamiDBVersionError`, explaining how to upgrade. (@parndt) - Raise `Hanami::CLI::UnsupportedDatabaseSchemeError` from `hanami db` commands for unsupported database URL schemes, and the new `Hanami::CLI::InvalidDatabaseURLError` for database URLs that cannot be parsed, rather than a `RuntimeError` or `URI::InvalidURIError`. Neither error includes the URL, since it may contain credentials. (@parndt) - Ignore SQLite's `-wal`, `-shm` and `-journal` files in the `.gitignore` generated by `hanami new`, by widening `db/*.sqlite` to `db/*.sqlite*`. (@cllns in #451) - Use Dry CLI 2.0 (@timriley) diff --git a/lib/hanami/cli/commands/app/db/utils/database.rb b/lib/hanami/cli/commands/app/db/utils/database.rb index 10cb8f13..43c5be0f 100644 --- a/lib/hanami/cli/commands/app/db/utils/database.rb +++ b/lib/hanami/cli/commands/app/db/utils/database.rb @@ -41,15 +41,10 @@ def sql DATABASE_SCHEME_MATCHER = /\A(?:jdbc:)?[a-z][a-z0-9+.-]*(?=:)/i private_constant :DATABASE_SCHEME_MATCHER - # Minimum hanami-db version providing the Hanami::DB::DatabaseURL helpers used here. - # - # hanami-db is an optional dependency, so hanami-cli's gemspec cannot require it. This - # means apps can upgrade hanami-cli while keeping an older hanami-db. - MINIMUM_HANAMI_DB_VERSION = "3.1.0" - private_constant :MINIMUM_HANAMI_DB_VERSION - def self.database_class(database_url) - ensure_hanami_db_version + # Required here rather than at the top of this file, since every app command loads + # this file, including in apps that do not use hanami-db. + require "hanami-db" adapter = Hanami::DB::DatabaseURL.adapter(database_url) @@ -62,16 +57,6 @@ def self.database_class(database_url) }.call end - # Requires hanami-db here rather than at the top of this file, since every app command - # loads this file, including in apps that do not use hanami-db. - def self.ensure_hanami_db_version - require "hanami-db" - return if defined?(Hanami::DB::DatabaseURL) - - raise Hanami::CLI::HanamiDBVersionError.new(MINIMUM_HANAMI_DB_VERSION, Hanami::DB::VERSION) - end - private_class_method :ensure_hanami_db_version - # Returns false when the URL cannot be parsed. Avoids raising from a `rescue`, since # the URI error (whose message includes the URL) would become the new error's cause. def self.parseable?(database_url) diff --git a/lib/hanami/cli/errors.rb b/lib/hanami/cli/errors.rb index 69377d91..d961ec26 100644 --- a/lib/hanami/cli/errors.rb +++ b/lib/hanami/cli/errors.rb @@ -119,17 +119,6 @@ def initialize(scheme) end end - # @since 3.1.0 - # @api public - class HanamiDBVersionError < Error - def initialize(minimum_version, installed_version) - super( - "hanami-cli #{Hanami::CLI::VERSION} requires hanami-db #{minimum_version} or later, " \ - "but #{installed_version} is installed. Please run `bundle update hanami-db`." - ) - end - end - # Does not include the URL itself, since it may contain credentials. # # @since 3.1.0 diff --git a/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb b/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb index 68248c66..2339e126 100644 --- a/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb +++ b/spec/unit/hanami/cli/commands/app/db/utils/database_spec.rb @@ -19,16 +19,6 @@ end end - it "raises an error when the installed hanami-db is too old" do - hide_const "Hanami::DB::DatabaseURL" - - expect { described_class.database_class("postgres://localhost/app") } - .to raise_error(Hanami::CLI::HanamiDBVersionError) { |error| - expect(error.message).to include "requires hanami-db 3.1.0 or later, but #{Hanami::DB::VERSION} is installed" - expect(error.message).to include "bundle update hanami-db" - } - end - it "raises an error for unsupported schemes, without including the URL's credentials" do expect { described_class.database_class("oracle://user:secret@localhost/app") } .to raise_error(Hanami::CLI::UnsupportedDatabaseSchemeError, "`oracle' is not a supported db scheme") From a51ffc5fde8a0e40b0e3411edbe84333d9799f4e Mon Sep 17 00:00:00 2001 From: Philip Arndt Date: Thu, 5 Nov 2026 10:59:54 +1300 Subject: [PATCH 6/6] Add PR number to changelog entry for database URL errors Match the other CHANGELOG entries, which link to the pull request that made each change. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a32f6b4f..586ba33b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ and this project adheres to [Break Versioning](https://www.taoensso.com/break-ve ### Changed - Print clearer errors when Postgres CLI commands fail. (@mddelk in #437) -- Raise `Hanami::CLI::UnsupportedDatabaseSchemeError` from `hanami db` commands for unsupported database URL schemes, and the new `Hanami::CLI::InvalidDatabaseURLError` for database URLs that cannot be parsed, rather than a `RuntimeError` or `URI::InvalidURIError`. Neither error includes the URL, since it may contain credentials. (@parndt) +- Raise `Hanami::CLI::UnsupportedDatabaseSchemeError` from `hanami db` commands for unsupported database URL schemes, and the new `Hanami::CLI::InvalidDatabaseURLError` for database URLs that cannot be parsed, rather than a `RuntimeError` or `URI::InvalidURIError`. Neither error includes the URL, since it may contain credentials. (@parndt in #463) - Ignore SQLite's `-wal`, `-shm` and `-journal` files in the `.gitignore` generated by `hanami new`, by widening `db/*.sqlite` to `db/*.sqlite*`. (@cllns in #451) - Use Dry CLI 2.0 (@timriley) - Commands now use the I/O streams given by Dry CLI 2.0's `Dry::CLI::Command`, and take `stdout:`, `stderr:` and `stdin:` in place of `out:` and `err:`. (@timriley)