hanami-cli 2.1.1 → 2.2.0.beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +29 -13
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +28 -0
- data/Gemfile +6 -1
- data/README.md +13 -7
- data/docker-compose.yml +14 -0
- data/hanami-cli.gemspec +2 -2
- data/lib/hanami/cli/command.rb +2 -2
- data/lib/hanami/cli/commands/app/command.rb +2 -16
- data/lib/hanami/cli/commands/app/db/command.rb +148 -0
- data/lib/hanami/cli/commands/app/db/create.rb +21 -11
- data/lib/hanami/cli/commands/app/db/drop.rb +21 -10
- data/lib/hanami/cli/commands/app/db/migrate.rb +50 -12
- data/lib/hanami/cli/commands/app/db/prepare.rb +68 -0
- data/lib/hanami/cli/commands/app/db/seed.rb +22 -21
- data/lib/hanami/cli/commands/app/db/structure/dump.rb +32 -7
- data/lib/hanami/cli/commands/app/db/structure/load.rb +54 -0
- data/lib/hanami/cli/commands/app/db/utils/database.rb +100 -75
- data/lib/hanami/cli/commands/app/db/utils/mysql.rb +59 -6
- data/lib/hanami/cli/commands/app/db/utils/postgres.rb +42 -21
- data/lib/hanami/cli/commands/app/db/utils/sqlite.rb +58 -10
- data/lib/hanami/cli/commands/app/db/version.rb +14 -8
- data/lib/hanami/cli/commands/app/generate/action.rb +4 -3
- data/lib/hanami/cli/commands/app/generate/command.rb +60 -0
- data/lib/hanami/cli/commands/app/generate/component.rb +49 -0
- data/lib/hanami/cli/commands/app/generate/migration.rb +47 -0
- data/lib/hanami/cli/commands/app/generate/operation.rb +26 -0
- data/lib/hanami/cli/commands/app/generate/part.rb +1 -1
- data/lib/hanami/cli/commands/app/generate/relation.rb +29 -0
- data/lib/hanami/cli/commands/app/generate/repo.rb +42 -0
- data/lib/hanami/cli/commands/app/generate/slice.rb +20 -3
- data/lib/hanami/cli/commands/app/generate/struct.rb +27 -0
- data/lib/hanami/cli/commands/app/install.rb +1 -1
- data/lib/hanami/cli/commands/app/middleware.rb +1 -1
- data/lib/hanami/cli/commands/app/server.rb +2 -2
- data/lib/hanami/cli/commands/app.rb +21 -2
- data/lib/hanami/cli/commands/gem/new.rb +78 -14
- data/lib/hanami/cli/errors.rb +28 -0
- data/lib/hanami/cli/files.rb +22 -0
- data/lib/hanami/cli/generators/app/action_context.rb +5 -13
- data/lib/hanami/cli/generators/app/component/component.erb +8 -0
- data/lib/hanami/cli/generators/app/component/slice_component.erb +8 -0
- data/lib/hanami/cli/generators/app/component.rb +61 -0
- data/lib/hanami/cli/generators/app/component_context.rb +82 -0
- data/lib/hanami/cli/generators/app/migration.rb +66 -0
- data/lib/hanami/cli/generators/app/operation.rb +49 -0
- data/lib/hanami/cli/generators/app/part_context.rb +5 -21
- data/lib/hanami/cli/generators/app/relation.rb +45 -0
- data/lib/hanami/cli/generators/app/repo.rb +41 -0
- data/lib/hanami/cli/generators/app/ruby_file_writer.rb +151 -0
- data/lib/hanami/cli/generators/app/slice/{entities.erb → operation.erb} +1 -3
- data/lib/hanami/cli/generators/app/slice/relation.erb +8 -0
- data/lib/hanami/cli/generators/app/slice/{slice.erb → repo.erb} +3 -1
- data/lib/hanami/cli/generators/app/slice/struct.erb +8 -0
- data/lib/hanami/cli/generators/app/slice.rb +14 -6
- data/lib/hanami/cli/generators/app/slice_context.rb +9 -2
- data/lib/hanami/cli/generators/app/struct.rb +40 -0
- data/lib/hanami/cli/generators/app/view_context.rb +4 -16
- data/lib/hanami/cli/generators/constants.rb +39 -0
- data/lib/hanami/cli/generators/context.rb +48 -0
- data/lib/hanami/cli/generators/gem/app/action.erb +3 -0
- data/lib/hanami/cli/generators/gem/app/env.erb +4 -0
- data/lib/hanami/cli/generators/gem/app/gemfile.erb +11 -0
- data/lib/hanami/cli/generators/gem/app/gitignore.erb +4 -1
- data/lib/hanami/cli/generators/gem/app/operation.erb +13 -0
- data/lib/hanami/cli/generators/gem/app/relation.erb +10 -0
- data/lib/hanami/cli/generators/gem/app/repo.erb +10 -0
- data/lib/hanami/cli/generators/gem/app/struct.erb +10 -0
- data/lib/hanami/cli/generators/gem/app.rb +19 -0
- data/lib/hanami/cli/ruby_file_generator.rb +123 -0
- data/lib/hanami/cli/version.rb +1 -1
- metadata +39 -17
- data/lib/hanami/cli/commands/app/db/create_migration.rb +0 -32
- data/lib/hanami/cli/commands/app/db/reset.rb +0 -28
- data/lib/hanami/cli/commands/app/db/rollback.rb +0 -81
- data/lib/hanami/cli/commands/app/db/sample_data.rb +0 -42
- data/lib/hanami/cli/commands/app/db/setup.rb +0 -26
- data/lib/hanami/cli/commands/app/db/utils/database_config.rb +0 -60
- data/lib/hanami/cli/generators/app/slice/repository.erb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d62ed9aeff86f86693ffdf5acafb274e6e97a535a177bf46131c8c33141fc0e9
|
4
|
+
data.tar.gz: 86da7248a20712451a83b8e5167870e34fd508f2e5f41a107d9bf3a4dea1d376
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: affe042dfe0daf2dc93e1252b06d2d51dd5ea605c1287ad2500371bed6ee98e902cf9d19667458f86edadabb671f923b986bcd2a76a0e7d8821f4e0b9af6ecf6
|
7
|
+
data.tar.gz: b1a097c66c10495ef31fd0783083d542ac6e7a5be7ab94f11b9e1a0d68dc865e04d6f970e08b88d33dd3939b47736cc8893989cb037d070d3c5d2ff86d35ccad
|
data/.github/workflows/ci.yml
CHANGED
@@ -27,15 +27,9 @@ jobs:
|
|
27
27
|
- "3.3"
|
28
28
|
- "3.2"
|
29
29
|
- "3.1"
|
30
|
-
|
30
|
+
env:
|
31
|
+
POSTGRES_BASE_URL: postgres://postgres:password@localhost:5432/hanami_cli_test
|
31
32
|
steps:
|
32
|
-
- uses: ravsamhq/notify-slack-action@v1
|
33
|
-
if: always()
|
34
|
-
with:
|
35
|
-
status: ${{ job.status }}
|
36
|
-
notify_when: "failure"
|
37
|
-
env:
|
38
|
-
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
39
33
|
- uses: actions/checkout@v1
|
40
34
|
- name: Install package dependencies
|
41
35
|
run: "[ -e $APT_DEPS ] || sudo apt-get install -y --no-install-recommends $APT_DEPS"
|
@@ -43,10 +37,32 @@ jobs:
|
|
43
37
|
uses: ruby/setup-ruby@v1
|
44
38
|
with:
|
45
39
|
ruby-version: ${{matrix.ruby}}
|
46
|
-
|
47
|
-
run: |
|
48
|
-
gem install bundler --no-document
|
49
|
-
- name: Bundle install
|
50
|
-
run: bundle install --jobs 4 --retry 3
|
40
|
+
bundler-cache: true
|
51
41
|
- name: Run all tests
|
52
42
|
run: bundle exec rake spec
|
43
|
+
services:
|
44
|
+
mysql:
|
45
|
+
image: mysql:latest
|
46
|
+
env:
|
47
|
+
MYSQL_ROOT_PASSWORD: password
|
48
|
+
ports:
|
49
|
+
- 3307:3306
|
50
|
+
options: >-
|
51
|
+
--health-cmd "mysqladmin ping"
|
52
|
+
--health-interval 10s
|
53
|
+
--health-timeout 5s
|
54
|
+
--health-retries 3
|
55
|
+
postgres:
|
56
|
+
# Use postgres:14 for CLI compatibility with ubuntu-latest, currently ubuntu-22.04
|
57
|
+
# See https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md
|
58
|
+
image: postgres:14
|
59
|
+
env:
|
60
|
+
POSTGRES_USER: postgres
|
61
|
+
POSTGRES_PASSWORD: password
|
62
|
+
ports:
|
63
|
+
- 5432:5432
|
64
|
+
options: >-
|
65
|
+
--health-cmd pg_isready
|
66
|
+
--health-interval 10s
|
67
|
+
--health-timeout 5s
|
68
|
+
--health-retries 5
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,34 @@
|
|
2
2
|
|
3
3
|
Hanami Command Line Interface
|
4
4
|
|
5
|
+
## v2.2.0.beta2 - 2024-09-25
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
- [Tim Riley] MySQL support for `db` commands (#226)
|
10
|
+
- [Tim Riley] Support for multiple gateways in `db` commands (#232, #234, #237, #238)
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
|
14
|
+
- [Kyle Plump, Tim Riley] Delete `.keep` files when generating new files into previously empty directory (#224)
|
15
|
+
- [Sean Collins] Add `db/*.sqlite` to the `.gitignore` in new apps (#210)
|
16
|
+
- [Sean Collins] Print warnings for misconfigured databases when running `db` commands (#211)
|
17
|
+
|
18
|
+
## v2.2.0.beta1 - 2024-07-16
|
19
|
+
|
20
|
+
### Added
|
21
|
+
|
22
|
+
- [Sean Collins] Generate db files in `hanami new` and `generate slice`
|
23
|
+
- [Tim Riley] Add `db` commands: `create`, `drop`, `migrate`, `structure dump` `structure load`, `seed` `prepare`, `version`
|
24
|
+
- [Tim Riley] Support SQLite and Postgres for `db` commands
|
25
|
+
- [Sean Collins] Add `generate` commands for db components: `generate migration`, `generate relation`, `generate repo`, `generate struct`
|
26
|
+
- [Krzysztof] Add `generate component` command
|
27
|
+
- [Sean Collins] Add `generate operation` command
|
28
|
+
|
29
|
+
### Changed
|
30
|
+
|
31
|
+
- Drop support for Ruby 3.0
|
32
|
+
|
5
33
|
## v2.1.1 - 2024-03-19
|
6
34
|
|
7
35
|
### Fixed
|
data/Gemfile
CHANGED
@@ -12,13 +12,18 @@ end
|
|
12
12
|
gem "hanami", github: "hanami/hanami", branch: "main"
|
13
13
|
gem "hanami-assets", github: "hanami/assets", branch: "main"
|
14
14
|
gem "hanami-controller", github: "hanami/controller", branch: "main"
|
15
|
+
gem "hanami-db", github: "hanami/db", branch: "main"
|
15
16
|
gem "hanami-router", github: "hanami/router", branch: "main"
|
16
17
|
gem "hanami-utils", github: "hanami/utils", branch: "main"
|
17
18
|
|
18
|
-
gem "dry-
|
19
|
+
gem "dry-system", github: "dry-rb/dry-system", branch: "main"
|
19
20
|
|
20
21
|
gem "rack"
|
21
22
|
|
23
|
+
gem "mysql2"
|
24
|
+
gem "pg"
|
25
|
+
gem "sqlite3"
|
26
|
+
|
22
27
|
gem "hanami-devtools", github: "hanami/devtools", branch: "main"
|
23
28
|
|
24
29
|
group :test do
|
data/README.md
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
# Hanami::CLI
|
2
2
|
|
3
|
-
CLI commands for [full-stack Hanami applications](`https://github.com/hanami/hanami`).
|
3
|
+
This library contains all of the CLI commands for [full-stack Hanami applications](`https://github.com/hanami/hanami`).
|
4
4
|
|
5
|
-
**NOTE**: For versions 0.4 and below, there was a general purpose CLI utility library with this
|
5
|
+
**NOTE**: For versions 0.4 and below, there was a general purpose CLI utility library with this name.
|
6
|
+
That library has since been renamed to [dry-rb/dry-cli](https://github.com/dry-rb/dry-cli).
|
7
|
+
Please update your Gemfiles accordingly.
|
6
8
|
|
7
9
|
## Status
|
8
10
|
|
9
11
|
[](https://badge.fury.io/rb/hanami-cli)
|
10
|
-
[](https://github.com/hanami/cli/actions?query=workflow%3Aci+branch%3Amain)
|
11
13
|
[](https://depfu.com/github/hanami/cli?project=Bundler)
|
12
14
|
|
13
15
|
## Contact
|
@@ -15,12 +17,14 @@ CLI commands for [full-stack Hanami applications](`https://github.com/hanami/han
|
|
15
17
|
- Home page: http://hanamirb.org
|
16
18
|
- Mailing List: http://hanamirb.org/mailing-list
|
17
19
|
- Bugs/Issues: https://github.com/hanami/cli/issues
|
18
|
-
-
|
20
|
+
- API Doc: http://rubydoc.info/gems/hanami-cli
|
19
21
|
- Chat: http://chat.hanamirb.org
|
20
22
|
|
21
|
-
##
|
23
|
+
## Installation
|
22
24
|
|
23
|
-
**Hanami::
|
25
|
+
**Hanami::CLI** supports Ruby (MRI) 3.1+
|
26
|
+
|
27
|
+
This library is a dependency of the main `hanami` gem, so installing that is the best way to get and use this gem.
|
24
28
|
|
25
29
|
## Usage
|
26
30
|
|
@@ -30,6 +34,8 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
30
34
|
|
31
35
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
36
|
|
37
|
+
In order to run all of the tests, you should run `docker compose up` separately, to run a `postgres` server.
|
38
|
+
|
33
39
|
## Contributing
|
34
40
|
|
35
41
|
Bug reports and pull requests are welcome on GitHub at https://github.com/hanami/cli. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/hanami/cli/blob/main/CODE_OF_CONDUCT.md).
|
@@ -44,4 +50,4 @@ Everyone interacting in the `Hanami::CLI` project's codebases, issue trackers, c
|
|
44
50
|
|
45
51
|
## Copyright
|
46
52
|
|
47
|
-
Copyright © 2014 Hanami Team – Released under MIT License
|
53
|
+
Copyright © 2014–2024 Hanami Team – Released under MIT License
|
data/docker-compose.yml
ADDED
data/hanami-cli.gemspec
CHANGED
@@ -28,10 +28,10 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
29
29
|
spec.require_paths = ["lib"]
|
30
30
|
spec.metadata["rubygems_mfa_required"] = "true"
|
31
|
-
spec.required_ruby_version = ">= 3.
|
31
|
+
spec.required_ruby_version = ">= 3.1"
|
32
32
|
|
33
33
|
spec.add_dependency "bundler", "~> 2.1"
|
34
|
-
spec.add_dependency "dry-cli", "~> 1.0", "
|
34
|
+
spec.add_dependency "dry-cli", "~> 1.0", ">= 1.1.0"
|
35
35
|
spec.add_dependency "dry-files", "~> 1.0", ">= 1.0.2", "< 2"
|
36
36
|
spec.add_dependency "dry-inflector", "~> 1.0", "< 2"
|
37
37
|
spec.add_dependency "rake", "~> 13.0"
|
data/lib/hanami/cli/command.rb
CHANGED
@@ -23,11 +23,11 @@ module Hanami
|
|
23
23
|
def self.new(
|
24
24
|
out: $stdout,
|
25
25
|
err: $stderr,
|
26
|
-
fs: Hanami::CLI::Files.new,
|
26
|
+
fs: Hanami::CLI::Files.new(out: out),
|
27
27
|
inflector: Dry::Inflector.new,
|
28
28
|
**opts
|
29
29
|
)
|
30
|
-
super
|
30
|
+
super
|
31
31
|
end
|
32
32
|
|
33
33
|
# Returns a new command.
|
@@ -71,12 +71,12 @@ module Hanami
|
|
71
71
|
#
|
72
72
|
# @since 2.0.0
|
73
73
|
# @api public
|
74
|
-
def run_command(klass,
|
74
|
+
def run_command(klass, ...)
|
75
75
|
klass.new(
|
76
76
|
out: out,
|
77
77
|
inflector: app.inflector,
|
78
78
|
fs: Hanami::CLI::Files,
|
79
|
-
).call(
|
79
|
+
).call(...)
|
80
80
|
end
|
81
81
|
|
82
82
|
# Executes a given block and prints string to the `out` stream with details of the time
|
@@ -111,20 +111,6 @@ module Hanami
|
|
111
111
|
out.puts "!!! => #{desc.inspect} FAILED"
|
112
112
|
end
|
113
113
|
end
|
114
|
-
|
115
|
-
# This is NOT AVAILABLE as of the 2.0.0 release.
|
116
|
-
#
|
117
|
-
# @api private
|
118
|
-
def database
|
119
|
-
@database ||= Commands::App::DB::Utils::Database[app]
|
120
|
-
end
|
121
|
-
|
122
|
-
# This is NOT AVAILABLE as of the 2.0.0 release.
|
123
|
-
#
|
124
|
-
# @api private
|
125
|
-
def database_config
|
126
|
-
database.config
|
127
|
-
end
|
128
114
|
end
|
129
115
|
end
|
130
116
|
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "shellwords"
|
4
|
+
require_relative "utils/database"
|
5
|
+
|
6
|
+
module Hanami
|
7
|
+
module CLI
|
8
|
+
module Commands
|
9
|
+
module App
|
10
|
+
module DB
|
11
|
+
# Base class for `hanami` CLI commands intended to be executed within an existing Hanami
|
12
|
+
# app.
|
13
|
+
#
|
14
|
+
# @since 2.2.0
|
15
|
+
# @api private
|
16
|
+
class Command < App::Command
|
17
|
+
option :app, required: false, type: :flag, default: false, desc: "Use app database"
|
18
|
+
option :slice, required: false, desc: "Use database for slice"
|
19
|
+
|
20
|
+
attr_reader :system_call
|
21
|
+
|
22
|
+
def initialize(
|
23
|
+
out:, err:,
|
24
|
+
system_call: SystemCall.new,
|
25
|
+
**opts
|
26
|
+
)
|
27
|
+
super(out: out, err: err, **opts)
|
28
|
+
@system_call = system_call
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_command(klass, ...)
|
32
|
+
klass.new(
|
33
|
+
out: out,
|
34
|
+
inflector: inflector,
|
35
|
+
fs: fs,
|
36
|
+
system_call: system_call,
|
37
|
+
).call(...)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def databases(app: false, slice: nil, gateway: nil)
|
43
|
+
if gateway && !app && !slice
|
44
|
+
err.puts "When specifying --gateway, an --app or --slice must also be given"
|
45
|
+
exit 1
|
46
|
+
end
|
47
|
+
|
48
|
+
databases =
|
49
|
+
if slice
|
50
|
+
[database_for_slice(slice, gateway: gateway)]
|
51
|
+
elsif app
|
52
|
+
[database_for_slice(self.app, gateway: gateway)]
|
53
|
+
else
|
54
|
+
all_databases
|
55
|
+
end
|
56
|
+
|
57
|
+
databases.flatten
|
58
|
+
end
|
59
|
+
|
60
|
+
def database_for_slice(slice, gateway: nil)
|
61
|
+
unless slice.is_a?(Class) && slice < Hanami::Slice
|
62
|
+
slice_name = inflector.underscore(Shellwords.shellescape(slice)).to_sym
|
63
|
+
slice = app.slices[slice_name]
|
64
|
+
end
|
65
|
+
|
66
|
+
ensure_database_slice slice
|
67
|
+
|
68
|
+
databases = build_databases(slice)
|
69
|
+
|
70
|
+
if gateway
|
71
|
+
databases.fetch(gateway.to_sym) do
|
72
|
+
err.puts %(No gateway "#{gateway}" in #{slice})
|
73
|
+
exit 1
|
74
|
+
end
|
75
|
+
else
|
76
|
+
databases.values
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def all_databases # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
|
81
|
+
slices = [app] + app.slices.with_nested
|
82
|
+
|
83
|
+
slice_gateways_by_database_url = slices.each_with_object({}) { |slice, hsh|
|
84
|
+
db_provider_source = slice.container.providers[:db]&.source
|
85
|
+
next unless db_provider_source
|
86
|
+
|
87
|
+
db_provider_source.database_urls.each do |gateway, url|
|
88
|
+
hsh[url] ||= []
|
89
|
+
hsh[url] << {slice: slice, gateway: gateway}
|
90
|
+
end
|
91
|
+
}
|
92
|
+
|
93
|
+
slice_gateways_by_database_url.each_with_object([]) { |(url, slice_gateways), arr|
|
94
|
+
slice_gateways_with_config = slice_gateways.select {
|
95
|
+
_1[:slice].root.join("config", "db").directory?
|
96
|
+
}
|
97
|
+
|
98
|
+
db_slice_gateway = slice_gateways_with_config.first || slice_gateways.first
|
99
|
+
database = Utils::Database.database_class(url).new(
|
100
|
+
slice: db_slice_gateway.fetch(:slice),
|
101
|
+
gateway_name: db_slice_gateway.fetch(:gateway),
|
102
|
+
system_call: system_call
|
103
|
+
)
|
104
|
+
|
105
|
+
warn_on_misconfigured_database database, slice_gateways.map { _1.fetch(:slice) }
|
106
|
+
|
107
|
+
arr << database
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
def build_databases(slice)
|
112
|
+
Utils::Database.from_slice(slice: slice, system_call: system_call)
|
113
|
+
end
|
114
|
+
|
115
|
+
def ensure_database_slice(slice)
|
116
|
+
return if slice.container.providers[:db]
|
117
|
+
|
118
|
+
out.puts "#{slice} does not have a :db provider."
|
119
|
+
exit 1
|
120
|
+
end
|
121
|
+
|
122
|
+
def warn_on_misconfigured_database(database, slices) # rubocop:disable Metrics/AbcSize
|
123
|
+
if slices.length > 1
|
124
|
+
out.puts <<~STR
|
125
|
+
WARNING: Database #{database.name} is configured for multiple config/db/ directories:
|
126
|
+
|
127
|
+
#{slices.map { "- " + _1.root.relative_path_from(_1.app.root).join("config", "db").to_s }.join("\n")}
|
128
|
+
|
129
|
+
Migrating database using #{database.slice.slice_name.to_s.inspect} slice only.
|
130
|
+
|
131
|
+
STR
|
132
|
+
elsif !database.db_config_dir?
|
133
|
+
relative_path = database.slice.root
|
134
|
+
.relative_path_from(database.slice.app.root)
|
135
|
+
.join("config", "db").to_s
|
136
|
+
|
137
|
+
out.puts <<~STR
|
138
|
+
WARNING: Database #{database.name} expects the folder #{relative_path}/ to exist but it does not.
|
139
|
+
|
140
|
+
STR
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -1,23 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "../../app/command"
|
4
|
-
|
5
3
|
module Hanami
|
6
4
|
module CLI
|
7
5
|
module Commands
|
8
6
|
module App
|
9
7
|
module DB
|
10
8
|
# @api private
|
11
|
-
class Create <
|
12
|
-
desc "Create
|
9
|
+
class Create < DB::Command
|
10
|
+
desc "Create databases"
|
11
|
+
|
12
|
+
option :gateway, required: false, desc: "Use database for gateway"
|
13
|
+
|
14
|
+
def call(app: false, slice: nil, gateway: nil, command_exit: method(:exit), **)
|
15
|
+
exit_codes = []
|
16
|
+
|
17
|
+
databases(app: app, slice: slice, gateway: gateway).each do |database|
|
18
|
+
result = database.exec_create_command
|
19
|
+
exit_codes << result.exit_code if result.respond_to?(:exit_code)
|
20
|
+
|
21
|
+
if result == true || result.successful?
|
22
|
+
out.puts "=> database #{database.name} created"
|
23
|
+
else
|
24
|
+
out.puts "=> failed to create database #{database.name}"
|
25
|
+
out.puts "#{result.err}\n"
|
26
|
+
end
|
27
|
+
end
|
13
28
|
|
14
|
-
|
15
|
-
|
16
|
-
if database.create_command
|
17
|
-
out.puts "=> database #{database.name} created"
|
18
|
-
else
|
19
|
-
out.puts "=> failed to create database #{database.name}"
|
20
|
-
exit $?.exitstatus
|
29
|
+
exit_codes.each do |code|
|
30
|
+
break command_exit.(code) if code > 0
|
21
31
|
end
|
22
32
|
end
|
23
33
|
end
|
@@ -1,22 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "../../app/command"
|
4
|
-
|
5
3
|
module Hanami
|
6
4
|
module CLI
|
7
5
|
module Commands
|
8
6
|
module App
|
9
7
|
module DB
|
10
8
|
# @api private
|
11
|
-
class Drop <
|
12
|
-
desc "Delete
|
9
|
+
class Drop < DB::Command
|
10
|
+
desc "Delete databases"
|
11
|
+
|
12
|
+
option :gateway, required: false, desc: "Use database for gateway"
|
13
|
+
|
14
|
+
def call(app: false, slice: nil, gateway: nil, **)
|
15
|
+
exit_codes = []
|
16
|
+
|
17
|
+
databases(app: app, slice: slice, gateway: gateway).each do |database|
|
18
|
+
result = database.exec_drop_command
|
19
|
+
exit_codes << result.exit_code if result.respond_to?(:exit_code)
|
20
|
+
|
21
|
+
if result == true || result.successful?
|
22
|
+
out.puts "=> database #{database.name} dropped"
|
23
|
+
else
|
24
|
+
out.puts "=> failed to drop database #{database.name}"
|
25
|
+
out.puts "#{result.err}\n"
|
26
|
+
end
|
27
|
+
end
|
13
28
|
|
14
|
-
|
15
|
-
|
16
|
-
if database.drop_command
|
17
|
-
out.puts "=> database #{database.name} dropped"
|
18
|
-
else
|
19
|
-
out.puts "=> failed to drop #{database.name}"
|
29
|
+
exit_codes.each do |code|
|
30
|
+
break exit code if code > 0
|
20
31
|
end
|
21
32
|
end
|
22
33
|
end
|
@@ -1,38 +1,76 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "../../app/command"
|
4
|
-
require_relative "structure/dump"
|
5
|
-
|
6
3
|
module Hanami
|
7
4
|
module CLI
|
8
5
|
module Commands
|
9
6
|
module App
|
10
7
|
module DB
|
11
8
|
# @api private
|
12
|
-
class Migrate <
|
9
|
+
class Migrate < DB::Command
|
13
10
|
desc "Migrates database"
|
14
11
|
|
12
|
+
option :gateway, required: false, desc: "Use database for gateway"
|
15
13
|
option :target, desc: "Target migration number", aliases: ["-t"]
|
14
|
+
option :dump, required: false, type: :boolean, default: true,
|
15
|
+
desc: "Dump the database structure after migrating"
|
16
|
+
|
17
|
+
def call(target: nil, app: false, slice: nil, gateway: nil, dump: true, command_exit: method(:exit), **)
|
18
|
+
databases(app: app, slice: slice, gateway: gateway).each do |database|
|
19
|
+
if migrations_dir_missing?(database)
|
20
|
+
warn_on_missing_migrations_dir(database)
|
21
|
+
elsif no_migrations?(database)
|
22
|
+
warn_on_empty_migrations_dir(database)
|
23
|
+
else
|
24
|
+
migrate_database(database, target: target)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
run_command(Structure::Dump, app: app, slice: slice, gateway: gateway, command_exit: command_exit) if dump
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
16
32
|
|
17
|
-
|
18
|
-
|
19
|
-
return true if Dir[File.join(app.root, "db/migrate/*.rb")].empty?
|
33
|
+
def migrate_database(database, target:)
|
34
|
+
return true unless database.migrations_dir?
|
20
35
|
|
21
36
|
measure "database #{database.name} migrated" do
|
22
37
|
if target
|
23
|
-
run_migrations(target: Integer(target))
|
38
|
+
database.run_migrations(target: Integer(target))
|
24
39
|
else
|
25
|
-
run_migrations
|
40
|
+
database.run_migrations
|
26
41
|
end
|
27
42
|
|
28
43
|
true
|
29
44
|
end
|
30
45
|
end
|
31
46
|
|
32
|
-
|
47
|
+
def migrations_dir_missing?(database)
|
48
|
+
!database.migrations_dir?
|
49
|
+
end
|
50
|
+
|
51
|
+
def no_migrations?(database)
|
52
|
+
database.sequel_migrator.files.empty?
|
53
|
+
end
|
54
|
+
|
55
|
+
def warn_on_missing_migrations_dir(database)
|
56
|
+
out.puts <<~STR
|
57
|
+
WARNING: Database #{database.name} expects migrations to be located within #{relative_migrations_path(database)} but that folder does not exist.
|
58
|
+
|
59
|
+
No database migrations can be run for this database.
|
60
|
+
STR
|
61
|
+
end
|
62
|
+
|
63
|
+
def warn_on_empty_migrations_dir(database)
|
64
|
+
out.puts <<~STR
|
65
|
+
NOTE: Empty database migrations folder (#{relative_migrations_path(database)}) for #{database.name}
|
66
|
+
STR
|
67
|
+
end
|
33
68
|
|
34
|
-
def
|
35
|
-
database
|
69
|
+
def relative_migrations_path(database)
|
70
|
+
database
|
71
|
+
.migrations_path
|
72
|
+
.relative_path_from(database.slice.app.root)
|
73
|
+
.to_s + "/"
|
36
74
|
end
|
37
75
|
end
|
38
76
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
module CLI
|
5
|
+
module Commands
|
6
|
+
module App
|
7
|
+
module DB
|
8
|
+
# @api private
|
9
|
+
class Prepare < DB::Command
|
10
|
+
desc "Prepare databases"
|
11
|
+
|
12
|
+
def call(app: false, slice: nil, **)
|
13
|
+
command_exit = -> code { throw :command_exited, code }
|
14
|
+
command_exit_arg = {command_exit: command_exit}
|
15
|
+
|
16
|
+
# Since any slice may have multiple databases, we need to run the steps below in a
|
17
|
+
# particular order to satisfy our ROM/Sequel's migrator, which requires _all_ the
|
18
|
+
# databases in a slice to be created before we can use it.
|
19
|
+
#
|
20
|
+
# So before we do anything else, make sure to create/load every database first.
|
21
|
+
databases(app: app, slice: slice).each do |database|
|
22
|
+
command_args = {
|
23
|
+
**command_exit_arg,
|
24
|
+
app: database.slice.app?,
|
25
|
+
slice: database.slice,
|
26
|
+
gateway: database.gateway_name.to_s
|
27
|
+
}
|
28
|
+
|
29
|
+
exit_code = catch :command_exited do
|
30
|
+
unless database.exists?
|
31
|
+
run_command(DB::Create, **command_args)
|
32
|
+
run_command(DB::Structure::Load, **command_args)
|
33
|
+
end
|
34
|
+
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
return exit exit_code if exit_code.to_i > 1
|
39
|
+
end
|
40
|
+
|
41
|
+
# Once all databases are created, the migrator will properly load for each slice, and
|
42
|
+
# we can migrate each database.
|
43
|
+
databases(app: app, slice: slice).each do |database|
|
44
|
+
command_args = {
|
45
|
+
**command_exit_arg,
|
46
|
+
app: database.slice.app?,
|
47
|
+
slice: database.slice,
|
48
|
+
gateway: database.gateway_name.to_s
|
49
|
+
}
|
50
|
+
|
51
|
+
exit_code = catch :command_exited do
|
52
|
+
run_command(DB::Migrate, **command_args)
|
53
|
+
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
return exit exit_code if exit_code.to_i > 1
|
58
|
+
end
|
59
|
+
|
60
|
+
# Finally, load the seeds for the slice overall, which is a once-per-slice operation.
|
61
|
+
run_command(DB::Seed, app: app, slice: slice)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|