tomo 1.1.2 β†’ 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5b5ce43b616e968193b178c5bdcf299a066fff72803f7e5d08e5b2f3031da36
4
- data.tar.gz: df6827b5fccc78461849a2aa226f5fc625bc8d5aa3dece49dcd029451e27bc27
3
+ metadata.gz: b4cb608a21d6ce3191225519a3b467a226f0e0b4d1675f08bbed82fd6379696b
4
+ data.tar.gz: 0cb9a00e0eb50501c727d4e58db8b0c5cc686b7e27714ec7bdc11b95387f977d
5
5
  SHA512:
6
- metadata.gz: 71978c54069ac069386d7eac411fe85548492c8bc7f58dbbb48fed6791070c6abad2035d664111c93a827a1b8b03774cdfa1bf14fbd30c370066cee83d630bfb
7
- data.tar.gz: f96b68f1c8f6457548c1d28276a3c599a99c02d4075cdb894d8ec16a9bc06b9f540758db3f7752ee3d5d964120db363145b8f2e0e1718c77610b36e0c386c02e
6
+ metadata.gz: 875563989d848c0dcec9d1b18110712d91603fa734d1aa6fbb5dad454a0911808543f0c0ae9da9510732625d36bc94a0ee5d64d136192e5b4df77b9e130b2292
7
+ data.tar.gz: 936d56fefb5c964b9e19d92ec328cf148de894da697e88d80146428abfefb307551820d9aaba1967d539a2ec22e8f465bf9296bdc364093de9e750e4734bbc05
data/README.md CHANGED
@@ -1,26 +1,26 @@
1
1
  # Tomo
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/tomo.svg)](https://rubygems.org/gems/tomo)
4
- [![Travis](https://img.shields.io/travis/mattbrictson/tomo.svg?label=travis)](https://travis-ci.org/mattbrictson/tomo)
5
- [![Circle](https://circleci.com/gh/mattbrictson/tomo.svg?style=shield)](https://app.circleci.com/pipelines/github/mattbrictson/tomo?branch=master)
4
+ [![Travis](https://img.shields.io/travis/com/mattbrictson/tomo.svg?label=travis)](https://travis-ci.com/github/mattbrictson/tomo)
5
+ [![Circle](https://circleci.com/gh/mattbrictson/tomo/tree/main.svg?style=shield)](https://app.circleci.com/pipelines/github/mattbrictson/tomo?branch=main)
6
6
  [![Code Climate](https://codeclimate.com/github/mattbrictson/tomo/badges/gpa.svg)](https://codeclimate.com/github/mattbrictson/tomo)
7
7
 
8
- Tomo is a friendly command-line tool for deploying Rails apps. It is a new alternative to Capistrano, Mina, and Shipit that aims for simplicity and developer happiness.
8
+ Tomo is a friendly command-line tool for deploying Rails apps.
9
9
 
10
10
  πŸ’» Rich command-line interface with built-in bash completions<br/>
11
11
  ☁️ Multi-environment and role-based multi-host support<br/>
12
12
  πŸ’Ž Everything you need to deploy a basic Rails app out of the box<br/>
13
13
  πŸ”Œ Easily extensible for polyglot projects (not just Rails!)<br/>
14
- πŸ’‘ Concise, helpful error messages<br/>
15
14
  πŸ“š Quality documentation<br/>
16
15
  πŸ”¬ Minimal dependencies<br/>
17
16
 
18
- See [how tomo compares](https://tomo-deploy.com/comparisons/) to other Ruby deployment tools.
17
+ [β†’ See how tomo compares to other Ruby deployment tools like Capistrano and Mina.](https://tomo-deploy.com/comparisons/)
19
18
 
20
19
  ---
21
20
 
22
21
  - [Quick start](#quick-start)
23
22
  - [Usage](#usage)
23
+ - [Extending tomo](#extending-tomo)
24
24
  - [Tutorials](#tutorials)
25
25
  - [Reference documentation](#reference-documentation)
26
26
  - [FAQ](#faq)
@@ -31,21 +31,19 @@ See [how tomo compares](https://tomo-deploy.com/comparisons/) to other Ruby depl
31
31
 
32
32
  ## Quick start
33
33
 
34
+ #### Installation
35
+
34
36
  Tomo is distributed as a ruby gem. To install:
35
37
 
36
38
  ```
37
39
  $ gem install tomo
38
40
  ```
39
41
 
40
- For instructions on setting up bash completions, run:
41
-
42
- ```
43
- $ tomo completion-script
44
- ```
42
+ > πŸ’‘ **Protip:** run `tomo completion-script` for instructions on setting up bash completions.
45
43
 
46
44
  #### Configuring a project
47
45
 
48
- Tomo is configured via a `.tomo/config.rb` file in your project. To get started, you can use `tomo init` to generate a configuration that works for a basic Rails app.
46
+ Tomo is configured via a `.tomo/config.rb` file in your project. To get started, run `tomo init` to generate a configuration that works for a basic Rails app.
49
47
 
50
48
  ![$ tomo init](./readme_images/tomo-init.png)
51
49
 
@@ -64,7 +62,7 @@ host "user@hostname.or.ip.address"
64
62
  set application: "my-rails-app"
65
63
  set deploy_to: "/var/www/%{application}"
66
64
  set git_url: "git@github.com:my-username/my-rails-app.git"
67
- set git_branch: "master"
65
+ set git_branch: "main"
68
66
  # ...
69
67
 
70
68
  setup do
@@ -87,20 +85,25 @@ deploy do
87
85
  end
88
86
  ```
89
87
 
90
- Check out the [configuration docs](https://tomo-deploy.com/configuration/) for a complete reference.
88
+ #### Next steps
89
+
90
+ [β†’ The reference docs have a complete guide to tomo configuration.](https://tomo-deploy.com/configuration/)<br>
91
+ [β†’ Check out the **Deploying Rails From Scratch** tutorial for a step-by-step guide to using tomo with a real app.](https://tomo-deploy.com/tutorials/deploying-rails-from-scratch/)
91
92
 
92
93
  ## Usage
93
94
 
94
- Tomo gives you easy-to-use commands for three common use cases:
95
+ Once your project is configured, you can:
96
+
97
+ 1. Run `tomo setup` to prepare the remote host for its first deploy.
98
+ 2. Run `tomo deploy` to deploy your app.
99
+ 3. Use `tomo run` to invoke one-off tasks, like launching a Rails console.
95
100
 
96
- 1. `tomo setup` prepares a remote host for its first deploy
97
- 2. `tomo deploy` performs a deployment
98
- 3. `tomo run` lets you invoke one-off tasks
101
+ > πŸ’‘ **Protip:** add `-h` or `--help` when running any of these commands to see detailed docs and examples.
99
102
 
100
- ### Setup
103
+ ### `tomo setup`
101
104
 
102
105
  `tomo setup` prepares the remote host for its first deploy by sequentially running the
103
- [setup](https://tomo-deploy.com/configuration#setupblock) list of tasks specified in `.tomo/config.rb`. These tasks typically create directories, initialize data stores, install prerequisite tools, and perform other one-time actions that are necessary before a deploy can take place.
106
+ `setup` list of tasks specified in `.tomo/config.rb`. These tasks typically create directories, initialize data stores, install prerequisite tools, and perform other one-time actions that are necessary before a deploy can take place.
104
107
 
105
108
  Out of the box, tomo will:
106
109
 
@@ -109,9 +112,12 @@ Out of the box, tomo will:
109
112
  - Create all necessary deployment directories
110
113
  - Create the Rails database, load the schema, and insert seed data
111
114
 
112
- ### Deploy
115
+ [β†’ Here is the default list of tasks invoked by the setup command.](https://tomo-deploy.com/configuration#setupblock)<br>
116
+ [β†’ The `tomo setup` section of the reference docs explains supported command-line options.](https://tomo-deploy.com/commands/setup/)
113
117
 
114
- Whereas `tomo setup` is typically run once, you can use `tomo deploy` every time you want to deploy a new version of your app. The deploy command will sequentially run the [deploy](https://tomo-deploy.com/configuration#deployblock) list of tasks specified in `.tomo/config.rb`. You can customize this list to meet the needs of your app. By default, tomo runs these tasks:
118
+ ### `tomo deploy`
119
+
120
+ Whereas `tomo setup` is typically run once, you can use `tomo deploy` every time you want to deploy a new version of your app. The deploy command will sequentially run the `deploy` list of tasks specified in `.tomo/config.rb`. You can customize this list to meet the needs of your app. By default, tomo runs these tasks:
115
121
 
116
122
  1. Create a release (using the [git:create_release](https://tomo-deploy.com/plugins/git#gitcreate_release) task)
117
123
  2. Build the project (e.g. [bundler:install](https://tomo-deploy.com/plugins/bundler#bundlerinstall), [rails:assets_precompile](https://tomo-deploy.com/plugins/rails#railsassets_precompile))
@@ -120,7 +126,13 @@ Whereas `tomo setup` is typically run once, you can use `tomo deploy` every time
120
126
  5. Restart the app to use the new current release (e.g. [puma:restart](https://tomo-deploy.com/plugins/puma#pumarestart))
121
127
  6. Perform any cleanup (e.g. [bundler:clean](https://tomo-deploy.com/plugins/bundler#bundlerclean))
122
128
 
123
- ### Run
129
+ > πŸ’‘ **Protip:** you can abbreviate tomo commands, like `tomo d` for `tomo deploy` or `tomo s` for `tomo setup`.
130
+
131
+ [β†’ Here is the default list of tasks invoked by the deploy command.](https://tomo-deploy.com/configuration#deployblock)<br>
132
+ [β†’ The `tomo deploy` section of the reference docs explains supported command-line options, like `--dry-run`.](https://tomo-deploy.com/commands/deploy/)
133
+
134
+
135
+ ### `tomo run [TASK]`
124
136
 
125
137
  Tomo can also `run` individual remote tasks on demand. You can use the `tasks` command to see the list of tasks tomo knows about.
126
138
 
@@ -130,9 +142,15 @@ One of the built-in Rails tasks is `rails:console`, which brings up a fully-inte
130
142
 
131
143
  ![$ tomo run rails:console](./readme_images/tomo-run-rails-console.png)
132
144
 
133
- ### Extending tomo
145
+ > πŸ’‘ **Protip:** you can shorten this as `tomo rails:console` (the `run` command is implied).
146
+
147
+ [β†’ The `tomo run` section of the reference docs explains supported command-line options and has more examples.](https://tomo-deploy.com/commands/run/)
148
+
134
149
 
135
- Tomo has many plugins built-in, but you can easily add your own to extend tomo with custom tasks. By convention, custom plugins are stored in `.tomo/plugins/`. These plugins can define tasks as plain ruby methods. For example:
150
+
151
+ ## Extending tomo
152
+
153
+ Tomo has a powerful plugin system that lets you extend tomo by installing Ruby gems (e.g. [tomo-plugin-sidekiq](https://github.com/mattbrictson/tomo-plugin-sidekiq)). You can also define plugins on the fly within your project by adding simple `.rb` files to `.tomo/plugins/`. These plugins can define tasks as plain ruby methods. For example:
136
154
 
137
155
  ```ruby
138
156
  # .tomo/plugins/my-plugin.rb
@@ -142,8 +160,6 @@ def hello
142
160
  end
143
161
  ```
144
162
 
145
- Use `remote.run` to execute shell scripts on the remote host, similar to how you would use Ruby's `system`. Project settings are accessible via `settings`, which is a plain Ruby hash.
146
-
147
163
  Load your plugin in `config.rb` like this:
148
164
 
149
165
  ```ruby
@@ -156,7 +172,9 @@ And run it!
156
172
 
157
173
  ![$ tomo run my-plugin:hello](./readme_images/tomo-run-hello.png)
158
174
 
159
- Read the [Writing Custom Tasks](https://tomo-deploy.com/tutorials/writing-custom-tasks/) tutorial for an in-depth guide to extending tomo.
175
+ [β†’ The **Writing Custom Tasks** tutorial has an in-depth explanation of how plugins work.](https://tomo-deploy.com/tutorials/writing-custom-tasks/)<br>
176
+ [β†’ The **TaskLibrary** API is tomo's DSL for building tasks.](https://tomo-deploy.com/api/TaskLibrary/)<br>
177
+ [β†’ The **Publishing a Plugin** tutorial explains how to package your plugin as a Ruby gem to share it with the community.](https://tomo-deploy.com/tutorials/publishing-a-plugin/)
160
178
 
161
179
  ## Tutorials
162
180
 
@@ -225,7 +243,7 @@ Next run `tomo setup` for _both_ apps; this will set everything up for both user
225
243
 
226
244
  ## Support
227
245
 
228
- This project is a labor of love and I can only spend a few hours a week maintaining it, at most. If you'd like to help by submitting a pull request, or if you've discovered a bug that needs my attention, please let me know. Check out [CONTRIBUTING.md](https://github.com/mattbrictson/tomo/blob/master/CONTRIBUTING.md) to get started. Happy hacking! β€”Matt
246
+ This project is a labor of love and I can only spend a few hours a week maintaining it, at most. If you'd like to help by submitting a pull request, or if you've discovered a bug that needs my attention, please let me know. Check out [CONTRIBUTING.md](https://github.com/mattbrictson/tomo/blob/main/CONTRIBUTING.md) to get started. Happy hacking! β€”Matt
229
247
 
230
248
  ## License
231
249
 
@@ -233,8 +251,8 @@ The gem is available as open source under the terms of the [MIT License](https:/
233
251
 
234
252
  ## Code of conduct
235
253
 
236
- Everyone interacting in the Tomo project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/mattbrictson/tomo/blob/master/CODE_OF_CONDUCT.md).
254
+ Everyone interacting in the Tomo project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/mattbrictson/tomo/blob/main/CODE_OF_CONDUCT.md).
237
255
 
238
256
  ## Contribution guide
239
257
 
240
- Interested in filing a bug report, feature request, or opening a PR? Excellent! Please read the short [CONTRIBUTING.md](https://github.com/mattbrictson/tomo/blob/master/CONTRIBUTING.md) guidelines before you dive in.
258
+ Interested in filing a bug report, feature request, or opening a PR? Excellent! Please read the short [CONTRIBUTING.md](https://github.com/mattbrictson/tomo/blob/main/CONTRIBUTING.md) guidelines before you dive in.
@@ -20,7 +20,7 @@ module Tomo
20
20
  class << self
21
21
  attr_accessor :show_backtrace
22
22
 
23
- def exit(status=true)
23
+ def exit(status=true) # rubocop:disable Style/OptionalBooleanParameter
24
24
  Process.exit(status)
25
25
  end
26
26
  end
@@ -55,7 +55,7 @@ module Tomo
55
55
  argv << "" if argv.shift == "--complete"
56
56
  end
57
57
 
58
- def lookup_command(argv) # rubocop:disable Metrics/CyclomaticComplexity
58
+ def lookup_command(argv)
59
59
  command_name = argv.first unless Completions.active? && argv.length == 1
60
60
  command_name = Abbrev.abbrev(COMMANDS.keys)[command_name]
61
61
  argv.shift if command_name
@@ -1,6 +1,6 @@
1
1
  class Tomo::CLI::Rules
2
2
  class Argument
3
- def initialize(label, multiple: false, required: false, values_proc:)
3
+ def initialize(label, values_proc:, multiple: false, required: false)
4
4
  @label = label
5
5
  @multiple = multiple
6
6
  @required = required
@@ -15,7 +15,7 @@ class Tomo::CLI::Rules
15
15
  state.parsed_arg(arg)
16
16
  end
17
17
 
18
- def candidates(literal: false, state:)
18
+ def candidates(state:, literal: false)
19
19
  values(state).reject { |val| literal && val.start_with?("-") }
20
20
  end
21
21
 
@@ -1,6 +1,6 @@
1
1
  class Tomo::CLI::Rules
2
2
  class Switch
3
- def initialize(key, *switches, required: false, callback_proc:, &convert_proc)
3
+ def initialize(key, *switches, callback_proc:, required: false, &convert_proc)
4
4
  @key = key
5
5
  @switches = switches
6
6
  @callback_proc = callback_proc
@@ -28,7 +28,7 @@ class Tomo::CLI::Rules
28
28
  state.parsed_option(key, value)
29
29
  end
30
30
 
31
- def candidates(switch=nil, literal: false, state:)
31
+ def candidates(switch=nil, state:, literal: false)
32
32
  return [] if literal
33
33
 
34
34
  vals = values(state)
@@ -70,6 +70,14 @@ module Tomo
70
70
  nil
71
71
  end
72
72
 
73
+ def git_branch
74
+ return unless File.file?(".git/config")
75
+
76
+ `git rev-parse --abbrev-ref HEAD`.chomp
77
+ rescue SystemCallError
78
+ nil
79
+ end
80
+
73
81
  def node_version
74
82
  `node --version`.chomp.sub(/^v/i, "")
75
83
  rescue SystemCallError
@@ -82,10 +90,29 @@ module Tomo
82
90
  nil
83
91
  end
84
92
 
93
+ def rubocop?
94
+ File.exist?(".rubocop.yml")
95
+ end
96
+
97
+ def erb_2_2_or_later?
98
+ erb_version = Gem::Version.new(ERB.version[/\d[\d.]+/])
99
+ Gem::Requirement.new(">= 2.2").satisfied_by?(erb_version)
100
+ end
101
+
102
+ def ruby_version_file?
103
+ File.exist?(".ruby-version")
104
+ end
105
+
85
106
  def config_rb_template(app)
86
107
  path = File.expand_path("../templates/config.rb.erb", __dir__)
87
108
  template = IO.read(path)
88
- ERB.new(template).result(binding)
109
+
110
+ # TODO: remove once we drop Ruby 2.5 support?
111
+ if erb_2_2_or_later?
112
+ ERB.new(template, trim_mode: "-").result(binding)
113
+ else
114
+ ERB.new(template, nil, "-").result(binding)
115
+ end
89
116
  end
90
117
  end
91
118
  end
@@ -90,7 +90,7 @@ module Tomo
90
90
  plugins_registry = PluginsRegistry.new
91
91
 
92
92
  (["core"] + plugins.uniq).each do |plug|
93
- if %w[. /].include?(plug[0])
93
+ if plug.start_with?(".", "/")
94
94
  plug = File.expand_path(plug, File.dirname(path)) unless path.nil?
95
95
  plugins_registry.load_plugin_from_path(plug)
96
96
  else
@@ -50,7 +50,7 @@ module Tomo
50
50
  HINT
51
51
  end
52
52
 
53
- def highlighted_lines
53
+ def highlighted_lines # rubocop:disable Metrics/AbcSize
54
54
  first = [1, error_line_no - 1].max
55
55
  last = [dsl_lines.length, error_line_no + 1].min
56
56
  width = last.to_s.length
@@ -39,7 +39,7 @@ module Tomo
39
39
  def constantize(path)
40
40
  parts = path.split("/")
41
41
  parts.reduce(Object) do |parent, part|
42
- child = part.gsub(/^[a-z]|_[a-z]/) { |str| str.chars.last.upcase }
42
+ child = part.gsub(/^[a-z]|_[a-z]/) { |str| str[-1].upcase }
43
43
  parent.const_get(child, false)
44
44
  end
45
45
  end
@@ -55,7 +55,7 @@ module Tomo
55
55
 
56
56
  def scan_for_plugins
57
57
  Gem.find_latest_files("#{PLUGIN_PREFIX}/*.rb").map do |file|
58
- file[%r{#{PLUGIN_PREFIX}/(.+).rb$}, 1].tr("/", "-")
58
+ file[%r{#{PLUGIN_PREFIX}/(.+).rb$}o, 1].tr("/", "-")
59
59
  end.uniq.sort
60
60
  end
61
61
  end
@@ -12,9 +12,10 @@ module Tomo
12
12
  def_delegators :@instance, :interactive?, :prompt, :menu
13
13
  end
14
14
 
15
- def initialize(env=ENV, input=$stdin)
15
+ def initialize(env=ENV, input=$stdin, output=$stdout)
16
16
  @env = env
17
17
  @input = input
18
+ @output = output
18
19
  end
19
20
 
20
21
  def interactive?
@@ -24,7 +25,7 @@ module Tomo
24
25
  def prompt(question)
25
26
  assert_interactive
26
27
 
27
- print question
28
+ output.print question
28
29
  line = input.gets
29
30
  raise_non_interactive if line.nil?
30
31
 
@@ -39,7 +40,7 @@ module Tomo
39
40
 
40
41
  private
41
42
 
42
- attr_reader :env, :input
43
+ attr_reader :env, :input, :output
43
44
 
44
45
  CI_VARS = %w[
45
46
  JENKINS_HOME
@@ -20,7 +20,7 @@ module Tomo
20
20
  path(:"#{method}_path")
21
21
  end
22
22
 
23
- def respond_to_missing?(method, include_private=false)
23
+ def respond_to_missing?(method, include_private)
24
24
  setting?(method) || super
25
25
  end
26
26
 
@@ -56,7 +56,7 @@ module Tomo::Plugin::Bundler
56
56
  raise_on_error: false
57
57
  )
58
58
  version = lockfile_tail[/BUNDLED WITH\n (\S+)$/, 1]
59
- return version if version
59
+ return version if version || dry_run?
60
60
 
61
61
  die <<~REASON
62
62
  Could not guess bundler version from Gemfile.lock.
@@ -12,7 +12,7 @@ module Tomo::Plugin::Core
12
12
  result.success?
13
13
  end
14
14
 
15
- def write(text: nil, template: nil, to:, append: false, **run_opts)
15
+ def write(to:, text: nil, template: nil, append: false, **run_opts)
16
16
  assert_text_or_template_required!(text, template)
17
17
  text = merge_template(template) unless template.nil?
18
18
  message = "Writing #{text.bytesize} bytes to #{to}"
@@ -41,7 +41,7 @@ module Tomo::Plugin::Core
41
41
  current = read_current_release
42
42
 
43
43
  remote.chdir(paths.releases) do
44
- releases = remote.list_files.grep(/^#{RELEASE_REGEXP}$/).sort
44
+ releases = remote.list_files.grep(/^#{RELEASE_REGEXP}$/o).sort
45
45
  desired_count -= 1 if releases.delete(current)
46
46
  return if releases.length <= desired_count
47
47
 
@@ -122,7 +122,7 @@ module Tomo::Plugin::Core
122
122
  result = remote.run("readlink", paths.current, raise_on_error: false, silent: true)
123
123
  return nil if result.failure?
124
124
 
125
- result.stdout.strip[%r{/(#{RELEASE_REGEXP})$}, 1]
125
+ result.stdout.strip[%r{/(#{RELEASE_REGEXP})$}o, 1]
126
126
  end
127
127
  end
128
128
  end
@@ -1,7 +1,7 @@
1
1
  require "monitor"
2
2
 
3
3
  module Tomo::Plugin::Env
4
- class Tasks < Tomo::TaskLibrary
4
+ class Tasks < Tomo::TaskLibrary # rubocop:disable Metrics/ClassLength
5
5
  include MonitorMixin
6
6
 
7
7
  def show
@@ -10,8 +10,8 @@ module Tomo::Plugin::Env
10
10
  end
11
11
 
12
12
  def setup
13
- update
14
13
  modify_bashrc
14
+ update
15
15
  end
16
16
 
17
17
  def update
@@ -103,12 +103,37 @@ module Tomo::Plugin::Env
103
103
  existing_rc = remote.capture("cat", paths.bashrc, raise_on_error: false)
104
104
  return if existing_rc.include?(". #{env_path}")
105
105
 
106
+ fail_if_different_app_already_configured!(existing_rc)
107
+
106
108
  remote.write(text: <<~BASHRC + existing_rc, to: paths.bashrc)
107
- if [ -f #{env_path} ]; then
108
- . #{env_path}
109
- fi
109
+ if [ -f #{env_path} ]; then # DO NOT MODIFY THESE LINES
110
+ . #{env_path} # ENV MAINTAINED BY TOMO
111
+ fi #{' ' * env_path.to_s.length}# END TOMO ENV
110
112
 
111
113
  BASHRC
112
114
  end
115
+
116
+ def fail_if_different_app_already_configured!(bashrc)
117
+ existing_env_path = bashrc[/\s*\.\s+(.+)\s+# ENV MAINTAINED BY TOMO/, 1]
118
+ return if existing_env_path.nil?
119
+
120
+ die <<~REASON
121
+ Based on the contents of #{paths.bashrc}, it looks like another application
122
+ is already being deployed via tomo to this host, using the following envrc
123
+ path:
124
+
125
+ #{existing_env_path}
126
+
127
+ Tomo is designed such that only one application can be deployed to a given
128
+ user@host. To deploy multiple applications to the same host, use a separate
129
+ deployer user per app. Refer to the tomo FAQ for details:
130
+
131
+ https://tomo-deploy.com/#faq
132
+
133
+ You may be receiving this message in error if you recently renamed or
134
+ reconfigured your application. In this case, remove the references to the
135
+ old envrc path in the host's #{paths.bashrc} and re-run env:setup.
136
+ REASON
137
+ end
113
138
  end
114
139
  end
@@ -7,7 +7,7 @@ module Tomo::Plugin
7
7
 
8
8
  helpers Tomo::Plugin::Git::Helpers
9
9
  tasks Tomo::Plugin::Git::Tasks
10
- defaults git_branch: "master",
10
+ defaults git_branch: nil,
11
11
  git_repo_path: "%{deploy_to}/git_repo",
12
12
  git_exclusions: [],
13
13
  git_env: { GIT_SSH_COMMAND: "ssh -o PasswordAuthentication=no -o StrictHostKeyChecking=no" },
@@ -8,6 +8,10 @@ module Tomo::Plugin::Rails
8
8
  remote.rails("console", settings[:run_args], attach: true)
9
9
  end
10
10
 
11
+ def db_console
12
+ remote.rails("dbconsole", "--include-password", settings[:run_args], attach: true)
13
+ end
14
+
11
15
  def db_migrate
12
16
  remote.rake("db:migrate")
13
17
  end
@@ -31,8 +31,7 @@ module Tomo::Plugin::Rbenv
31
31
  end
32
32
 
33
33
  def compile_ruby
34
- require_setting :rbenv_ruby_version
35
- ruby_version = settings[:rbenv_ruby_version]
34
+ ruby_version = version_setting || extract_ruby_ver_from_version_file
36
35
 
37
36
  unless ruby_installed?(ruby_version)
38
37
  logger.info(
@@ -51,5 +50,22 @@ module Tomo::Plugin::Rbenv
51
50
  end
52
51
  false
53
52
  end
53
+
54
+ def version_setting
55
+ settings[:rbenv_ruby_version]
56
+ end
57
+
58
+ def extract_ruby_ver_from_version_file
59
+ path = paths.release.join(".ruby-version")
60
+ version = remote.capture("cat", path, raise_on_error: false).strip
61
+ return version unless version.empty?
62
+
63
+ return RUBY_VERSION if dry_run?
64
+
65
+ die <<~REASON
66
+ Could not guess ruby version from .ruby-version file.
67
+ Use the :rbenv_ruby_version setting to specify the version of ruby to install.
68
+ REASON
69
+ end
54
70
  end
55
71
  end
@@ -7,7 +7,7 @@ module Tomo
7
7
  @concurrency = concurrency
8
8
  end
9
9
 
10
- def to_s # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity
10
+ def to_s # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
11
11
  desc = []
12
12
  threads = [applicable_hosts.length, concurrency].min
13
13
  desc << "CONCURRENTLY (#{threads} THREADS):" if threads > 1
@@ -82,7 +82,7 @@ module Tomo
82
82
  end
83
83
 
84
84
  def export_env
85
- exports = @env.reject { |_, value| value.nil? }
85
+ exports = @env.compact
86
86
  return if exports.empty?
87
87
 
88
88
  [
@@ -26,7 +26,7 @@ module Tomo
26
26
  end
27
27
 
28
28
  def ssh_subprocess(script, verbose: false)
29
- ssh_args = build_args(script, verbose)
29
+ ssh_args = build_args(script, verbose: verbose)
30
30
  handle_data = ->(data) { logger.script_output(script, data) }
31
31
 
32
32
  logger.script_start(script)
@@ -50,7 +50,7 @@ module Tomo
50
50
  Tomo.logger
51
51
  end
52
52
 
53
- def build_args(script, verbose=false)
53
+ def build_args(script, verbose: false)
54
54
  options.build_args(host, script, control_path, verbose)
55
55
  end
56
56
 
@@ -15,10 +15,10 @@ module Tomo
15
15
 
16
16
  def assert_valid_executable!
17
17
  result = begin
18
- ChildProcess.execute(executable, "-V")
19
- rescue StandardError => e
20
- handle_bad_executable(e)
21
- end
18
+ ChildProcess.execute(executable, "-V")
19
+ rescue StandardError => e
20
+ handle_bad_executable(e)
21
+ end
22
22
 
23
23
  Tomo.logger.debug(result.output)
24
24
  return if result.success? && supported?(result.output)
@@ -1,3 +1,6 @@
1
+ <% if rubocop? -%>
2
+ # rubocop:disable Style/FormatStringToken
3
+ <% end -%>
1
4
  plugin "git"
2
5
  plugin "env"
3
6
  plugin "bundler"
@@ -11,11 +14,13 @@ host "user@hostname.or.ip.address"
11
14
 
12
15
  set application: <%= app.inspect %>
13
16
  set deploy_to: "/var/www/%{application}"
17
+ <% unless ruby_version_file? -%>
14
18
  set rbenv_ruby_version: <%= RUBY_VERSION.inspect %>
19
+ <% end -%>
15
20
  set nodenv_node_version: <%= node_version&.inspect || "nil # FIXME" %>
16
21
  set nodenv_yarn_version: <%= yarn_version.inspect %>
17
22
  set git_url: <%= git_origin_url&.inspect || "nil # FIXME" %>
18
- set git_branch: "master"
23
+ set git_branch: <%= git_branch&.inspect || "nil # FIXME" %>
19
24
  set git_exclusions: %w[
20
25
  .tomo/
21
26
  spec/
@@ -72,3 +77,6 @@ deploy do
72
77
  run "bundler:clean"
73
78
  run "core:log_revision"
74
79
  end
80
+ <% if rubocop? -%>
81
+ # rubocop:enable Style/FormatStringToken
82
+ <% end -%>
@@ -1,7 +1,7 @@
1
1
  module Tomo
2
2
  module Testing
3
3
  module CLIExtensions
4
- def exit(status=true)
4
+ def exit(status=true) # rubocop:disable Style/OptionalBooleanParameter
5
5
  raise MockedExitError, status
6
6
  end
7
7
  end
@@ -80,9 +80,9 @@ module Tomo
80
80
  end
81
81
 
82
82
  def build_image
83
- Local.capture(
84
- "docker build #{build_dir}"
85
- )[/Successfully built (\S+)$/i, 1]
83
+ tag = "tomo_testing:latest"
84
+ Local.capture("docker build --tag #{tag} #{build_dir}")
85
+ tag
86
86
  end
87
87
 
88
88
  def start_container
@@ -1,3 +1,3 @@
1
1
  module Tomo
2
- VERSION = "1.1.2".freeze
2
+ VERSION = "1.4.1".freeze
3
3
  end
metadata CHANGED
@@ -1,141 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tomo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Brictson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-13 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: bundler
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '2.0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '2.0'
27
- - !ruby/object:Gem::Dependency
28
- name: concurrent-ruby
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '1.1'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.1'
41
- - !ruby/object:Gem::Dependency
42
- name: minitest
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '5.11'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '5.11'
55
- - !ruby/object:Gem::Dependency
56
- name: minitest-ci
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '3.4'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '3.4'
69
- - !ruby/object:Gem::Dependency
70
- name: minitest-reporters
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '1.3'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '1.3'
83
- - !ruby/object:Gem::Dependency
84
- name: rake
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '13.0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '13.0'
97
- - !ruby/object:Gem::Dependency
98
- name: rubocop
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - '='
102
- - !ruby/object:Gem::Version
103
- version: 0.85.1
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - '='
109
- - !ruby/object:Gem::Version
110
- version: 0.85.1
111
- - !ruby/object:Gem::Dependency
112
- name: rubocop-minitest
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - '='
116
- - !ruby/object:Gem::Version
117
- version: 0.9.0
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - '='
123
- - !ruby/object:Gem::Version
124
- version: 0.9.0
125
- - !ruby/object:Gem::Dependency
126
- name: rubocop-performance
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - '='
130
- - !ruby/object:Gem::Version
131
- version: 1.6.1
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - '='
137
- - !ruby/object:Gem::Version
138
- version: 1.6.1
11
+ date: 2020-11-26 00:00:00.000000000 Z
12
+ dependencies: []
139
13
  description: Tomo is a feature-rich deployment tool that contains everything you need
140
14
  to deploy a basic Rails app out of the box. It has an opinionated, production-tested
141
15
  set of defaults, but is easily extensible via a well-documented plugin system. Unlike
@@ -191,7 +65,6 @@ files:
191
65
  - lib/tomo/configuration/environment.rb
192
66
  - lib/tomo/configuration/glob.rb
193
67
  - lib/tomo/configuration/plugin_file_not_found_error.rb
194
- - lib/tomo/configuration/plugin_resolver.rb
195
68
  - lib/tomo/configuration/plugins_registry.rb
196
69
  - lib/tomo/configuration/plugins_registry/file_resolver.rb
197
70
  - lib/tomo/configuration/plugins_registry/gem_resolver.rb
@@ -298,7 +171,7 @@ metadata:
298
171
  bug_tracker_uri: https://github.com/mattbrictson/tomo/issues
299
172
  changelog_uri: https://github.com/mattbrictson/tomo/releases
300
173
  source_code_uri: https://github.com/mattbrictson/tomo
301
- homepage_uri: https://tomo-deploy.com/
174
+ homepage_uri: https://github.com/mattbrictson/tomo
302
175
  documentation_uri: https://tomo-deploy.com/
303
176
  post_install_message:
304
177
  rdoc_options: []
@@ -1,63 +0,0 @@
1
- module Tomo
2
- class Configuration
3
- class PluginResolver
4
- PLUGIN_PREFIX = "tomo/plugin".freeze
5
- private_constant :PLUGIN_PREFIX
6
-
7
- def self.resolve(name)
8
- new(name).plugin_module
9
- end
10
-
11
- def initialize(name)
12
- @name = name
13
- end
14
-
15
- def plugin_module
16
- plugin_path = [PLUGIN_PREFIX, name.tr("-", "/")].join("/")
17
- require plugin_path
18
-
19
- plugin = constantize(plugin_path)
20
- assert_compatible_api(plugin)
21
-
22
- plugin
23
- rescue LoadError => e
24
- raise unless e.message.match?(/\s#{Regexp.quote(plugin_path)}$/)
25
-
26
- raise_unknown_plugin_error(e)
27
- end
28
-
29
- private
30
-
31
- attr_reader :name
32
-
33
- def assert_compatible_api(plugin)
34
- return if plugin.is_a?(::Tomo::PluginDSL)
35
-
36
- raise "#{plugin} does not extend Tomo::PluginDSL"
37
- end
38
-
39
- def constantize(path)
40
- parts = path.split("/")
41
- parts.reduce(Object) do |parent, part|
42
- child = part.gsub(/^[a-z]|_[a-z]/) { |str| str.chars.last.upcase }
43
- parent.const_get(child, false)
44
- end
45
- end
46
-
47
- def raise_unknown_plugin_error(error)
48
- UnknownPluginError.raise_with(
49
- error.message,
50
- name: name,
51
- gem_name: "#{PLUGIN_PREFIX}/#{name}".tr("/", "-"),
52
- known_plugins: scan_for_plugins
53
- )
54
- end
55
-
56
- def scan_for_plugins
57
- Gem.find_latest_files("#{PLUGIN_PREFIX}/*.rb").map do |file|
58
- file[%r{#{PLUGIN_PREFIX}/(.+).rb$}, 1].tr("/", "-")
59
- end.uniq.sort
60
- end
61
- end
62
- end
63
- end