deployless 0.0.2 → 0.0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aab6d3d445d5d9e5cff066a80cbdfb755223a78213501c7c8d5298a6de4ca770
4
- data.tar.gz: c8cd0548721f23df5816c120d2c4aa5e9f7d04181efced5e2eb51fde483e5687
3
+ metadata.gz: 0e90092e1f7b282631146db071f6f160f6710b9c9d5e0c0e91a2f4d8c213a2af
4
+ data.tar.gz: 43f10ccfb7c4c22c391a72006f4c7a034b43f0b1716a1c65afa064e72ae0d138
5
5
  SHA512:
6
- metadata.gz: b230388676174384f56d044272b83eaa32b0bd2600224a2997ea3d632aa2fcd7b2265dcfe6318682812772612a7aacc923a991f944646a2242cdaf2a3f60ff80
7
- data.tar.gz: e1d73bacec3fa78d4494a96a616f1dac3d8e84c663bf1b5926f5168a7a893109176b11cfa310a8451305dd2df24474318ad01963ceb9885355cf4494b7b14a31
6
+ metadata.gz: b630343cce61bb6a67f1429701e22fbaf92df7d73057f268a87eb9186189aabf77e2f1b5fbe00b6e11f9af2864e70cfa4a92e2e50b2992dafad8bfc6f33e8e1e
7
+ data.tar.gz: acfb13ca4f5040f3a44c776cd9370d42e995b156851230020d9810ae4f58e7eefb0e2c043a209c54b734466fd18f13b7b2a15a561b1eb1e04961a96db3a2398d
data/bin/dpls CHANGED
@@ -1,10 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'tty-option'
4
- require 'tty-prompt'
5
- require 'tty-file'
6
- require 'yaml'
7
-
8
3
  require_relative '../lib/deployless'
9
4
 
10
5
  class Command
@@ -13,6 +8,10 @@ class Command
13
8
  argument :command do
14
9
  desc "The command to run"
15
10
  end
11
+
12
+ argument :task do
13
+ desc "The task to run"
14
+ end
16
15
  end
17
16
 
18
17
  command = Command.new
@@ -21,41 +20,69 @@ command.parse(ARGV)
21
20
  case command.params['command']
22
21
  when 'init'
23
22
  prompt = TTY::Prompt.new
24
- result = prompt.collect do
23
+ configuration = prompt.collect do
25
24
  key(:deployment_setup).enum_select("Deployment setup:", ["Dokku"], required: true)
26
25
  key(:background_job_processor).enum_select("Background job processor:", ["None", "Sidekiq"], required: true)
27
- key(:production_server_ip).ask("Production server IP:", required: true)
28
- key(:production_server_username).ask("Production server username:", required: true, default: 'ubuntu')
29
- key(:ssh_key_path).ask("SSH key path:", required: true, default: '~/.ssh/id_rsa')
30
- key(:email).ask("Email:", required: true)
31
26
  key(:app_name).ask("Application name:", required: true)
32
- key(:domain).ask("Domain:", required: true)
27
+ key(:support_for_staging_environment).enum_select("Support for staging environment?:", ["Yes", "No"], required: true)
33
28
  end
34
29
 
35
- TTY::File.create_file('.deployless.yml', result.to_yaml)
36
- TTY::File.safe_append_to_file(".gitignore", ".deployless.yml")
37
- when 'prepare'
38
- prompt = TTY::Prompt.new
39
- config = YAML.load_file('.deployless.yml')
40
- dokku = ::Deployless::Dokku.new(config)
41
- dokku.configure
42
- dokku.install
43
- dokku.add_ssh_key
44
- dokku.create_app
45
- dokku.set_initial_environment_variables
46
- dokku.install_postgres
47
- result = "No"
48
-
49
- while result == "No"
50
- result = prompt.enum_select("Add DNS record for the domain #{config.fetch(:domain)} - type: A, value: #{config.fetch(:production_server_ip)}. Is it done?", ["Yes", "No"], required: true)
51
- if result == "No"
52
- puts "Please add DNS record for the domain #{config.fetch(:domain)} - type: A, value: #{config.fetch(:production_server_ip)} and confirm when done."
30
+ environments = %i[production]
31
+ environments << :staging if configuration.fetch(:support_for_staging_environment) == 'Yes'
32
+
33
+ environments.each do |environment|
34
+ puts "Configuring #{environment} environment"
35
+ configuration[environment] = prompt.collect do
36
+ key(:server_ip).ask("Server IP:", required: true)
37
+ key(:ssh_key_path).ask("SSH key path:", required: true, default: '~/.ssh/id_rsa')
38
+ key(:server_username).ask("Server username:", required: true, default: 'ubuntu')
39
+ key(:email).ask("Email:", required: true)
40
+ key(:domain).ask("Domain:", required: true)
53
41
  end
42
+
43
+ configuration[environment][:environment_variables] = {
44
+ secret_key_base: SecureRandom.hex(64),
45
+ rails_env: environment,
46
+ rake_env: environment,
47
+ rails_log_to_stdout: 'enabled',
48
+ rails_serve_static_files: 'enabled'
49
+ }
54
50
  end
55
51
 
56
- dokku.configure_domain
57
- dokku.configure_ssl
58
- dokku.print_instructions
52
+ TTY::File.create_file('.deployless.yml', configuration.to_yaml)
53
+ TTY::File.safe_append_to_file(".gitignore", ".deployless.yml")
54
+ when 'production', 'staging'
55
+ case command.params['task']
56
+ when 'console'
57
+ config = YAML.load_file('.deployless.yml')
58
+ raise ArgumentError, "Environment #{command.params['command']} is not configured" if config[command.params['command'].to_sym].nil?
59
+
60
+ provider = ::Deployless::Providers::DokkuProvider.new(
61
+ config: config,
62
+ environment: command.params['command']
63
+ )
64
+ provider.run_console
65
+ when 'prepare'
66
+ config = YAML.load_file('.deployless.yml')
67
+ raise ArgumentError, "Environment #{command.params['command']} is not configured" if config[command.params['command'].to_sym].nil?
68
+
69
+ provider = ::Deployless::Providers::DokkuProvider.new(
70
+ config: config,
71
+ environment: command.params['command']
72
+ )
73
+ provider.configure_environment
74
+ when 'update-env'
75
+ config = YAML.load_file('.deployless.yml')
76
+ raise ArgumentError, "Environment #{command.params['command']} is not configured" if config[command.params['command'].to_sym].nil?
77
+
78
+ provider = ::Deployless::Providers::DokkuProvider.new(
79
+ config: config,
80
+ environment: command.params['command']
81
+ )
82
+ provider.update_environment_variables
83
+ else
84
+ puts 'Unknown task'
85
+ end
59
86
  else
60
87
  puts 'Unknown command'
61
88
  end
@@ -0,0 +1,186 @@
1
+ require 'sshkit'
2
+ require 'sshkit/dsl'
3
+ require 'securerandom'
4
+
5
+ module Deployless
6
+ module Providers
7
+ class DokkuProvider
8
+ include SSHKit::DSL
9
+
10
+ AppAlreadyExists = Class.new(StandardError)
11
+
12
+ VERSION = '0.35.12'
13
+
14
+ def initialize(config:, environment:)
15
+ @config = config
16
+ @environment = environment
17
+ configure
18
+ end
19
+
20
+ def run_console
21
+ server_ip = env_config.fetch(:server_ip)
22
+
23
+ puts "Connecting to #{@environment} rails console..."
24
+ system("ssh -t dokku@#{server_ip} enter #{app_name} web rails c")
25
+ end
26
+
27
+ def configure_environment
28
+ install
29
+ add_ssh_key
30
+ create_app
31
+ update_environment_variables
32
+ install_postgres
33
+ install_redis if @config.fetch(:background_job_processor) == 'Sidekiq'
34
+
35
+ result = "No"
36
+ prompt = TTY::Prompt.new
37
+
38
+ while result == "No"
39
+ result = prompt.enum_select("Add DNS record for the domain #{env_config.fetch(:domain)} - type: A, value: #{env_config.fetch(:server_ip)}. Is it done?", ["Yes", "No"], required: true)
40
+ if result == "No"
41
+ puts "Please add DNS record for the domain #{env_config.fetch(:domain)} - type: A, value: #{env_config.fetch(:server_ip)} and confirm when done."
42
+ end
43
+ end
44
+
45
+ configure_domain
46
+ configure_ssl
47
+ print_instructions
48
+ end
49
+
50
+ def update_environment_variables
51
+ environment_variables = env_config.fetch(:environment_variables)
52
+
53
+ app = app_name
54
+ on [env_config.fetch(:server_ip)] do |host|
55
+ execute :dokku, 'config:set', app, environment_variables.map { |key, value| "#{key.to_s.upcase}=#{value}" }.join(' ')
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def configure
62
+ SSHKit::Backend::Netssh.configure do |ssh|
63
+ ssh.connection_timeout = 30
64
+ ssh.ssh_options = {
65
+ user: env_config.fetch(:server_username),
66
+ keys: [env_config.fetch(:ssh_key_path)], # Fixed array syntax for keys
67
+ forward_agent: false,
68
+ auth_methods: %w(publickey password keyboard-interactive) # Added additional auth methods
69
+ }
70
+ end
71
+ end
72
+
73
+ def install
74
+ on [env_config.fetch(:server_ip)] do |host|
75
+ unless test "dokku"
76
+ execute :wget, '-NP', '.', 'https://dokku.com/bootstrap.sh'
77
+ execute :sudo, "DOKKU_TAG=#{VERSION}", 'bash', 'bootstrap.sh'
78
+ end
79
+ end
80
+ end
81
+
82
+ def add_ssh_key
83
+ public_key = File.read(File.expand_path(env_config.fetch(:ssh_key_path) + '.pub'))
84
+
85
+ on [env_config.fetch(:server_ip)] do |host|
86
+ unless test :dokku, 'ssh-keys:list', 'admin'
87
+ execute "echo '#{public_key}' | sudo dokku ssh-keys:add admin"
88
+ end
89
+ end
90
+ end
91
+
92
+ def create_app
93
+ app = app_name
94
+ on [env_config.fetch(:server_ip)] do |host|
95
+ if test :dokku, 'apps:exists', app
96
+ raise AppAlreadyExists, "App #{app} is already created"
97
+ else
98
+ execute :dokku, 'apps:create', app
99
+ end
100
+ end
101
+ end
102
+
103
+ def install_postgres
104
+ app = app_name
105
+ on [env_config.fetch(:server_ip)] do |host|
106
+ unless test :dokku, 'postgres'
107
+ execute :sudo, 'dokku', 'plugin:install', 'https://github.com/dokku/dokku-postgres.git'
108
+ end
109
+
110
+ unless test :dokku, 'postgres:exists', "#{app}-db"
111
+ execute :dokku, 'postgres:create', "#{app}-db"
112
+ end
113
+
114
+ unless test :dokku, 'postgres:linked', "#{app}-db", app
115
+ execute :dokku, 'postgres:link', "#{app}-db", app
116
+ end
117
+ end
118
+ end
119
+
120
+ def install_redis
121
+ app = app_name
122
+ on [env_config.fetch(:server_ip)] do |host|
123
+ unless test :dokku, 'redis'
124
+ execute :sudo, 'dokku', 'plugin:install', 'https://github.com/dokku/dokku-redis.git'
125
+ end
126
+
127
+ unless test :dokku, 'redis:exists', "#{app}-redis"
128
+ execute :dokku, 'redis:create', "#{app}-redis"
129
+ end
130
+
131
+ unless test :dokku, 'redis:linked', "#{app}-redis", app
132
+ execute :dokku, 'redis:link', "#{app}-redis", app
133
+ end
134
+ end
135
+ end
136
+
137
+ def configure_domain
138
+ domain = env_config.fetch(:domain)
139
+ app = app_name
140
+
141
+ on [env_config.fetch(:server_ip)] do |host|
142
+ unless test("dokku domains:report #{app} | grep #{domain}")
143
+ execute :dokku, 'domains:clear-global'
144
+ execute :dokku, 'domains:clear', app
145
+ execute :dokku, 'domains:add', app, domain
146
+ end
147
+ end
148
+ end
149
+
150
+ def configure_ssl
151
+ email = env_config.fetch(:email)
152
+ app = app_name
153
+
154
+ on [env_config.fetch(:server_ip)] do |host|
155
+ unless test :dokku, 'letsencrypt'
156
+ execute :sudo, 'dokku', 'plugin:install', 'https://github.com/dokku/dokku-letsencrypt.git'
157
+ end
158
+
159
+ unless test("dokku letsencrypt:list | grep #{app}")
160
+ execute :dokku, 'letsencrypt:set', app, 'email', email
161
+ execute :dokku, 'letsencrypt:enable', app
162
+ end
163
+ end
164
+ end
165
+
166
+ def print_instructions
167
+ puts "Configure deployment by adding git remote:"
168
+ puts "git remote add dokku dokku@#{env_config.fetch(:server_ip)}:#{app_name}"
169
+ puts "Then you can deploy by running:"
170
+ puts "git push dokku main"
171
+ end
172
+
173
+ def env_config
174
+ @config.fetch(@environment.to_sym)
175
+ end
176
+
177
+ def app_name
178
+ if @environment == 'production'
179
+ @config.fetch(:app_name)
180
+ else
181
+ "#{@config.fetch(:app_name)}-#{@environment}"
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
@@ -3,7 +3,8 @@ module Deployless
3
3
  module_function
4
4
 
5
5
  def to_s
6
- '0.0.2'
6
+ '0.0.4'
7
7
  end
8
8
  end
9
9
  end
10
+
data/lib/deployless.rb CHANGED
@@ -1 +1,6 @@
1
- require_relative 'deployless/dokku'
1
+ require 'tty-option'
2
+ require 'tty-prompt'
3
+ require 'tty-file'
4
+ require 'yaml'
5
+
6
+ require_relative 'deployless/providers/dokku_provider'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deployless
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paweł Dąbrowski
@@ -109,7 +109,7 @@ extra_rdoc_files: []
109
109
  files:
110
110
  - bin/dpls
111
111
  - lib/deployless.rb
112
- - lib/deployless/dokku.rb
112
+ - lib/deployless/providers/dokku_provider.rb
113
113
  - lib/deployless/version.rb
114
114
  homepage: https://github.com/impactahead/deployless
115
115
  licenses:
@@ -1,104 +0,0 @@
1
- require 'sshkit'
2
- require 'sshkit/dsl'
3
- require 'securerandom'
4
-
5
- module Deployless
6
- class Dokku
7
- include SSHKit::DSL
8
-
9
- def initialize(config)
10
- @config = config
11
- end
12
-
13
- def configure
14
- SSHKit::Backend::Netssh.configure do |ssh|
15
- ssh.connection_timeout = 30
16
- ssh.ssh_options = {
17
- user: @config.fetch(:production_server_username),
18
- keys: %w(@config.fetch(:ssh_key_path)),
19
- forward_agent: false,
20
- auth_methods: %w(publickey)
21
- }
22
- end
23
- end
24
-
25
- def install
26
- on [@config.fetch(:production_server_ip)] do |host|
27
- execute :wget, '-NP', '.', 'https://dokku.com/bootstrap.sh'
28
- execute :sudo, 'DOKKU_TAG=v0.35.12', 'bash', 'bootstrap.sh'
29
- end
30
- end
31
-
32
- def add_ssh_key
33
- public_key = File.read(File.expand_path(@config.fetch(:ssh_key_path) + '.pub'))
34
-
35
- on [@config.fetch(:production_server_ip)] do |host|
36
- execute "echo '#{public_key}' | sudo dokku ssh-keys:add admin"
37
- end
38
- end
39
-
40
- def create_app
41
- app_name = @config.fetch(:app_name)
42
-
43
- on [@config.fetch(:production_server_ip)] do |host|
44
- execute :dokku, 'apps:create', app_name
45
- end
46
- end
47
-
48
- def set_initial_environment_variables
49
- app_name = @config.fetch(:app_name)
50
- secret_key_base = SecureRandom.hex(64)
51
-
52
- environment_variables = {
53
- 'SECRET_KEY_BASE' => secret_key_base,
54
- 'RAILS_ENV' => 'production',
55
- 'RAKE_ENV' => 'production',
56
- 'RAILS_LOG_TO_STDOUT' => 'enabled',
57
- 'RAILS_SERVE_STATIC_FILES' => 'enabled'
58
- }
59
-
60
- on [@config.fetch(:production_server_ip)] do |host|
61
- execute :dokku, 'config:set', app_name, environment_variables.map { |key, value| "#{key}=#{value}" }.join(' ')
62
- end
63
- end
64
-
65
- def install_postgres
66
- app_name = @config.fetch(:app_name)
67
-
68
- on [@config.fetch(:production_server_ip)] do |host|
69
- execute :sudo, 'dokku', 'plugin:install', 'https://github.com/dokku/dokku-postgres.git'
70
- execute :dokku, 'postgres:create', "#{app_name}-db"
71
- execute :dokku, 'postgres:link', "#{app_name}-db", app_name
72
- end
73
- end
74
-
75
- def configure_domain
76
- domain = @config.fetch(:domain)
77
- app_name = @config.fetch(:app_name)
78
-
79
- on [@config.fetch(:production_server_ip)] do |host|
80
- execute :dokku, 'domains:clear-global'
81
- execute :dokku, 'domains:clear', app_name
82
- execute :dokku, 'domains:add', app_name, domain
83
- end
84
- end
85
-
86
- def configure_ssl
87
- email = @config.fetch(:email)
88
- app_name = @config.fetch(:app_name)
89
-
90
- on [@config.fetch(:production_server_ip)] do |host|
91
- execute :sudo, 'dokku', 'plugin:install', 'https://github.com/dokku/dokku-letsencrypt.git'
92
- execute :dokku, 'letsencrypt:set', app_name, 'email', email
93
- execute :dokku, 'letsencrypt:enable', app_name
94
- end
95
- end
96
-
97
- def print_instructions
98
- puts "Configure deployment by adding git remote:"
99
- puts "git remote add dokku dokku@#{@config.fetch(:production_server_ip)}:#{@config.fetch(:app_name)}"
100
- puts "Then you can deploy by running:"
101
- puts "git push dokku main"
102
- end
103
- end
104
- end