bard 1.0.0 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +5 -0
  3. data/features/bard_check.feature +1 -1
  4. data/features/bard_push.feature +1 -1
  5. data/features/step_definitions/global_steps.rb +4 -4
  6. data/features/support/env.rb +1 -1
  7. data/features/support/io.rb +1 -1
  8. data/lib/bard/ci/github_actions.rb +3 -6
  9. data/lib/bard/ci/local.rb +0 -2
  10. data/lib/bard/ci.rb +10 -12
  11. data/lib/bard/cli/ci.rb +51 -0
  12. data/lib/bard/cli/data.rb +45 -0
  13. data/lib/bard/cli/deploy.rb +64 -0
  14. data/lib/bard/cli/hurt.rb +20 -0
  15. data/lib/bard/cli/install.rb +16 -0
  16. data/lib/bard/cli/master_key.rb +17 -0
  17. data/lib/bard/cli/open.rb +13 -0
  18. data/lib/bard/cli/ping.rb +18 -0
  19. data/lib/bard/cli/provision.rb +15 -0
  20. data/lib/bard/cli/run.rb +24 -0
  21. data/lib/bard/cli/setup.rb +45 -0
  22. data/lib/bard/cli/ssh.rb +14 -0
  23. data/lib/bard/cli/stage.rb +27 -0
  24. data/lib/bard/cli/vim.rb +13 -0
  25. data/lib/bard/cli.rb +21 -246
  26. data/lib/bard/command.rb +8 -6
  27. data/lib/bard/config.rb +2 -11
  28. data/lib/bard/copy.rb +15 -40
  29. data/lib/bard/git.rb +2 -4
  30. data/lib/bard/ping.rb +0 -1
  31. data/lib/bard/provision/apt.rb +16 -0
  32. data/lib/bard/provision/http.rb +1 -15
  33. data/lib/bard/provision/mysql.rb +0 -2
  34. data/lib/bard/provision/passenger.rb +2 -4
  35. data/lib/bard/provision/repo.rb +2 -2
  36. data/lib/bard/provision/rvm.rb +3 -2
  37. data/lib/bard/provision/ssh.rb +17 -10
  38. data/lib/bard/provision/user.rb +1 -0
  39. data/lib/bard/provision.rb +4 -21
  40. data/lib/bard/server.rb +29 -7
  41. data/lib/bard/version.rb +1 -1
  42. data/spec/bard/ci_spec.rb +10 -0
  43. data/spec/bard/config_spec.rb +83 -0
  44. data/spec/bard/server_spec.rb +127 -0
  45. metadata +24 -3
  46. /data/lib/bard/provision/{master_key.rb → masterkey.rb} +0 -0
data/lib/bard/cli.rb CHANGED
@@ -1,17 +1,9 @@
1
1
  # this file gets loaded in the CLI context, not the Rails boot context
2
2
 
3
3
  require "thor"
4
- require "bard/git"
5
- require "bard/ci"
6
- require "bard/copy"
7
- require "bard/github"
8
- require "bard/ping"
9
4
  require "bard/config"
10
5
  require "bard/command"
11
- require "bard/provision"
12
6
  require "term/ansicolor"
13
- require "open3"
14
- require "uri"
15
7
 
16
8
  module Bard
17
9
  class CLI < Thor
@@ -19,244 +11,24 @@ module Bard
19
11
 
20
12
  class_option :verbose, type: :boolean, aliases: :v
21
13
 
22
- desc "data --from=production --to=local", "copy database and assets from from to to"
23
- option :from, default: "production"
24
- option :to, default: "local"
25
- def data
26
- from = config[options[:from]]
27
- to = config[options[:to]]
28
-
29
- if to.key == :production
30
- url = to.ping.first
31
- puts yellow "WARNING: You are about to push data to production, overwriting everything that is there!"
32
- answer = ask("If you really want to do this, please type in the full HTTPS url of the production server:")
33
- if answer != url
34
- puts red("!!! ") + "Failed! We expected #{url}. Is this really where you want to overwrite all the data?"
35
- exit 1
36
- end
37
- end
38
-
39
- puts "Dumping #{from.key} database to file..."
40
- from.run! "bin/rake db:dump"
41
-
42
- puts "Transfering file from #{from.key} to #{to.key}..."
43
- from.copy_file "db/data.sql.gz", to: to, verbose: true
44
-
45
- puts "Loading file into #{to.key} database..."
46
- to.run! "bin/rake db:load"
47
-
48
- config.data.each do |path|
49
- puts "Synchronizing files in #{path}..."
50
- from.copy_dir path, to: to, verbose: true
51
- end
52
- end
53
-
54
- desc "master_key --from=production --to=local", "copy master key from from to to"
55
- option :from, default: "production"
56
- option :to, default: "local"
57
- def master_key
58
- from = config[options[:from]]
59
- to = config[options[:to]]
60
- from.copy_file "config/master.key", to:
61
- end
62
-
63
- desc "stage [branch=HEAD]", "pushes current branch, and stages it"
64
- def stage branch=Git.current_branch
65
- unless config.servers.key?(:production)
66
- raise Thor::Error.new("`bard stage` is disabled until a production server is defined. Until then, please use `bard deploy` to deploy to the staging server.")
67
- end
68
-
69
- run! "git push -u origin #{branch}", verbose: true
70
- config[:staging].run! "git fetch && git checkout -f origin/#{branch} && bin/setup"
71
- puts green("Stage Succeeded")
72
-
73
- ping :staging
74
- end
75
-
76
- option :"skip-ci", type: :boolean
77
- option :"local-ci", type: :boolean
78
- desc "deploy [TO=production]", "checks that current branch is a ff with master, checks with ci, merges into master, deploys to target, and then deletes branch."
79
- def deploy to=:production
80
- branch = Git.current_branch
81
-
82
- if branch == "master"
83
- if !Git.up_to_date_with_remote?(branch)
84
- run! "git push origin #{branch}:#{branch}"
85
- end
86
- invoke :ci, [branch], options.slice("local-ci") unless options["skip-ci"]
87
-
88
- else
89
- run! "git fetch origin master:master"
90
-
91
- unless Git.fast_forward_merge?("origin/master", branch)
92
- puts "The master branch has advanced. Attempting rebase..."
93
- run! "git rebase origin/master"
94
- end
95
-
96
- run! "git push -f origin #{branch}:#{branch}"
97
-
98
- invoke :ci, [branch], options.slice("local-ci") unless options["skip-ci"]
99
-
100
- run! "git push origin #{branch}:master"
101
- run! "git fetch origin master:master"
102
- end
103
-
104
- if `git remote` =~ /\bgithub\b/
105
- run! "git push github"
106
- end
107
-
108
- config[to].run! "git pull origin master && bin/setup"
109
-
110
- puts green("Deploy Succeeded")
111
-
112
- if branch != "master"
113
- puts "Deleting branch: #{branch}"
114
- run! "git push --delete origin #{branch}"
115
-
116
- if branch == Git.current_branch
117
- run! "git checkout master"
118
- end
119
-
120
- run! "git branch -D #{branch}"
121
- end
122
-
123
- ping to
124
- end
125
-
126
- option :"local-ci", type: :boolean
127
- option :status, type: :boolean
128
- desc "ci [branch=HEAD]", "runs ci against BRANCH"
129
- def ci branch=Git.current_branch
130
- ci = CI.new(project_name, branch, local: options["local-ci"])
131
- if ci.exists?
132
- return puts ci.status if options["status"]
133
-
134
- puts "Continuous integration: starting build on #{branch}..."
135
-
136
- success = ci.run do |elapsed_time, last_time|
137
- if last_time
138
- percentage = (elapsed_time.to_f / last_time.to_f * 100).to_i
139
- output = " Estimated completion: #{percentage}%"
140
- else
141
- output = " No estimated completion time. Elapsed time: #{elapsed_time} sec"
142
- end
143
- print "\x08" * output.length
144
- print output
145
- $stdout.flush
146
- end
147
-
148
- if success
149
- puts
150
- puts "Continuous integration: success!"
151
- puts "Deploying..."
152
- else
153
- puts
154
- puts ci.last_response
155
- puts ci.console
156
- puts red("Automated tests failed!")
157
- exit 1
158
- end
159
-
160
- else
161
- puts red("No CI found for #{project_name}!")
162
- puts "Re-run with --skip-ci to bypass CI, if you absolutely must, and know what you're doing."
163
- exit 1
164
- end
165
- end
166
-
167
- desc "open [server=production]", "opens the url in the web browser."
168
- def open server=:production
169
- exec "xdg-open #{config[server].ping.first}"
170
- end
171
-
172
- option :home, type: :boolean
173
- desc "ssh [to=production]", "logs into the specified server via SSH"
174
- def ssh to=:production
175
- config[to].exec! "exec $SHELL -l", home: options[:home]
176
- end
177
-
178
- desc "install", "copies bin/setup and bin/ci scripts into current project."
179
- def install
180
- install_files_path = File.expand_path(File.join(__dir__, "../../install_files/*"))
181
- system "cp -R #{install_files_path} bin/"
182
- github_files_path = File.expand_path(File.join(__dir__, "../../install_files/.github"))
183
- system "cp -R #{github_files_path} ./"
184
- end
185
-
186
- desc "provision [ssh_url]", "takes an ssh url to a raw ubuntu 22.04 install, and readies it in the shape of :production"
187
- def provision ssh_url
188
- Provision.call(config, ssh_url.dup) # dup unfreezes the string for later mutation
189
- end
190
-
191
- desc "setup", "installs app in nginx"
192
- def setup
193
- path = "/etc/nginx/sites-available/#{project_name}"
194
- dest_path = path.sub("sites-available", "sites-enabled")
195
- server_name = case ENV["RAILS_ENV"]
196
- when "production"
197
- (config[:production].ping.map do |str|
198
- "*.#{URI.parse(str).host}"
199
- end + ["_"]).join(" ")
200
- when "staging" then "#{project_name}.botandrose.com"
201
- else "#{project_name}.localhost"
202
- end
203
-
204
- system "sudo tee #{path} >/dev/null <<-EOF
205
- server {
206
- listen 80;
207
- server_name #{server_name};
208
-
209
- root #{Dir.pwd}/public;
210
- passenger_enabled on;
211
-
212
- location ~* \\.(ico|css|js|gif|jp?g|png|webp) {
213
- access_log off;
214
- if (\\$request_filename ~ \"-[0-9a-f]{32}\\.\") {
215
- expires max;
216
- add_header Cache-Control public;
217
- }
218
- }
219
- gzip_static on;
220
- }
221
- EOF"
222
- system "sudo ln -sf #{path} #{dest_path}" if !File.exist?(dest_path)
223
- system "sudo service nginx restart"
224
- end
225
-
226
- desc "ping [server=production]", "hits the server over http to verify that its up."
227
- def ping server=:production
228
- server = config[server]
229
- down_urls = Bard::Ping.call(config[server])
230
- down_urls.each { |url| puts "#{url} is down!" }
231
- exit 1 if down_urls.any?
232
- end
233
-
234
- # HACK: we don't use Thor::Base#run, so its okay to stomp on it here
235
- original_verbose, $VERBOSE = $VERBOSE, nil
236
- Thor::THOR_RESERVED_WORDS -= ["run"]
237
- $VERBOSE = original_verbose
238
-
239
- desc "run <command>", "run the given command on production"
240
- def run *args
241
- server = config[:production]
242
- server.run! *args, verbose: true
243
- end
244
-
245
- desc "hurt <command>", "reruns a command until it fails"
246
- def hurt *args
247
- 1.upto(Float::INFINITY) do |count|
248
- puts "Running attempt #{count}"
249
- system *args
250
- unless $?.success?
251
- puts "Ran #{count-1} times before failing"
252
- break
253
- end
254
- end
255
- end
256
-
257
- desc "vim [branch=master]", "open all files that have changed since master"
258
- def vim branch="master"
259
- exec "vim -p `git diff #{branch} --name-only | grep -v sass$ | tac`"
14
+ {
15
+ data: "Data",
16
+ stage: "Stage",
17
+ deploy: "Deploy",
18
+ ci: "CI",
19
+ master_key: "MasterKey",
20
+ setup: "Setup",
21
+ run: "Run",
22
+ open: "Open",
23
+ ssh: "SSH",
24
+ install: "Install",
25
+ provision: "Provision",
26
+ ping: "Ping",
27
+ hurt: "Hurt",
28
+ vim: "Vim",
29
+ }.each do |command, klass|
30
+ require "bard/cli/#{command}"
31
+ include const_get(klass)
260
32
  end
261
33
 
262
34
  def self.exit_on_failure? = true
@@ -273,6 +45,9 @@ EOF"
273
45
 
274
46
  def run!(...)
275
47
  Bard::Command.run!(...)
48
+ rescue Bard::Command::Error => e
49
+ puts red("!!! ") + "Running command failed: #{yellow(e.message)}"
50
+ exit 1
276
51
  end
277
52
  end
278
53
  end
data/lib/bard/command.rb CHANGED
@@ -1,5 +1,9 @@
1
+ require "open3"
2
+
1
3
  module Bard
2
4
  class Command < Struct.new(:command, :on, :home)
5
+ class Error < RuntimeError; end
6
+
3
7
  def self.run! command, on: :local, home: false, verbose: false, quiet: false
4
8
  new(command, on, home).run! verbose:, quiet:
5
9
  end
@@ -14,9 +18,7 @@ module Bard
14
18
 
15
19
  def run! verbose: false, quiet: false
16
20
  if !run(verbose:, quiet:)
17
- raise "Running command failed: #{full_command}"
18
- # puts red("!!! ") + "Running command failed: #{yellow(command)}"
19
- # exit 1
21
+ raise Error.new(full_command)
20
22
  end
21
23
  end
22
24
 
@@ -49,7 +51,6 @@ module Bard
49
51
  end
50
52
 
51
53
  def remote_command quiet: false
52
- uri = on.ssh_uri
53
54
  ssh_key = on.ssh_key ? "-i #{on.ssh_key} " : ""
54
55
  cmd = command
55
56
  if on.env
@@ -58,10 +59,11 @@ module Bard
58
59
  unless home
59
60
  cmd = "cd #{on.path} && #{cmd}"
60
61
  end
61
- cmd = "ssh -tt #{ssh_key}#{"-p#{uri.port} " if uri.port}#{uri.user}@#{uri.host} '#{cmd}'"
62
+ uri = on.ssh_uri
63
+ cmd = "ssh -tt #{ssh_key} -p#{uri.port} #{uri.user}@#{uri.host} '#{cmd}'"
62
64
  if on.gateway
63
65
  uri = on.ssh_uri(:gateway)
64
- cmd = "ssh -tt #{" -p#{uri.port} " if uri.port}#{uri.user}@#{uri.host} \"#{cmd}\""
66
+ cmd = "ssh -tt -p#{uri.port} #{uri.user}@#{uri.host} \"#{cmd}\""
65
67
  end
66
68
  cmd += " 2>&1" if quiet
67
69
  cmd
data/lib/bard/config.rb CHANGED
@@ -12,13 +12,6 @@ module Bard
12
12
  "./",
13
13
  false,
14
14
  ),
15
- theia: Server.new(
16
- project_name,
17
- :theia,
18
- "gubito@gubs.pagekite.me",
19
- "Sites/#{project_name}",
20
- false,
21
- ),
22
15
  gubs: Server.new(
23
16
  project_name,
24
17
  :gubs,
@@ -40,7 +33,7 @@ module Bard
40
33
  ),
41
34
  }
42
35
  if path && File.exist?(path)
43
- source = File.read(File.expand_path(path))
36
+ source = File.read(path)
44
37
  end
45
38
  if source
46
39
  instance_eval source
@@ -51,9 +44,7 @@ module Bard
51
44
 
52
45
  def server key, &block
53
46
  key = key.to_sym
54
- @servers[key] ||= Server.new(project_name, key)
55
- @servers[key].instance_eval &block if block_given?
56
- @servers[key]
47
+ @servers[key] = Server.define(project_name, key, &block)
57
48
  end
58
49
 
59
50
  def [] key
data/lib/bard/copy.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require "uri"
2
+ require "bard/command"
3
+
1
4
  module Bard
2
5
  class Copy < Struct.new(:path, :from, :to, :verbose)
3
6
  def self.file path, from:, to:, verbose: false
@@ -19,33 +22,20 @@ module Bard
19
22
  end
20
23
 
21
24
  def scp_using_local direction, server
22
- uri = URI.parse("ssh://#{server.gateway}")
23
- port = uri.port ? "-p#{uri.port}" : ""
24
- gateway = server.gateway ? "-oProxyCommand='ssh #{port} #{uri.user}@#{uri.host} -W %h:%p'" : ""
25
+ gateway = server.gateway ? "-oProxyCommand='ssh #{server.ssh_uri(:gateway)} -W %h:%p'" : ""
25
26
 
26
27
  ssh_key = server.ssh_key ? "-i #{server.ssh_key}" : ""
27
28
 
28
- uri = URI.parse("ssh://#{server.ssh}")
29
- port = uri.port ? "-P#{uri.port}" : ""
30
- from_and_to = [path, "#{uri.user}@#{uri.host}:#{server.path}/#{path}"]
31
-
29
+ from_and_to = [path, server.scp_uri(path)]
32
30
  from_and_to.reverse! if direction == :from
33
- command = "scp #{gateway} #{ssh_key} #{port} #{from_and_to.join(" ")}"
34
31
 
32
+ command = ["scp", gateway, ssh_key, *from_and_to].join(" ")
35
33
  Bard::Command.run! command, verbose: verbose
36
34
  end
37
35
 
38
36
  def scp_as_mediator
39
37
  raise NotImplementedError if from.gateway || to.gateway || from.ssh_key || to.ssh_key
40
-
41
- from_uri = URI.parse("ssh://#{from.ssh}")
42
- from_str = "scp://#{from_uri.user}@#{from_uri.host}:#{from_uri.port || 22}/#{from.path}/#{path}"
43
-
44
- to_uri = URI.parse("ssh://#{to.ssh}")
45
- to_str = "scp://#{to_uri.user}@#{to_uri.host}:#{to_uri.port || 22}/#{to.path}/#{path}"
46
-
47
- command = "scp -o ForwardAgent=yes #{from_str} #{to_str}"
48
-
38
+ command = "scp -o ForwardAgent=yes #{from.scp_uri(path)} #{to.scp_uri(path)}"
49
39
  Bard::Command.run! command, verbose: verbose
50
40
  end
51
41
 
@@ -55,46 +45,31 @@ module Bard
55
45
  elsif to.key == :local
56
46
  rsync_using_local :from, from
57
47
  else
58
- rsync_as_mediator from, to
48
+ rsync_as_mediator
59
49
  end
60
50
  end
61
51
 
62
52
  def rsync_using_local direction, server
63
- uri = URI.parse("ssh://#{server.gateway}")
64
- port = uri.port ? "-p#{uri.port}" : ""
65
- gateway = server.gateway ? "-oProxyCommand=\"ssh #{port} #{uri.user}@#{uri.host} -W %h:%p\"" : ""
53
+ gateway = server.gateway ? "-oProxyCommand=\"ssh #{server.ssh_uri(:gateway)} -W %h:%p\"" : ""
66
54
 
67
55
  ssh_key = server.ssh_key ? "-i #{server.ssh_key}" : ""
68
- uri = URI.parse("ssh://#{server.ssh}")
69
- port = uri.port ? "-p#{uri.port}" : ""
70
- ssh = "-e'ssh #{ssh_key} #{port} #{gateway}'"
56
+ ssh = "-e'ssh #{gateway} -p#{server.ssh_uri.port || 22}'"
71
57
 
72
- dest_path = path.dup
73
- dest_path = "./#{dest_path}"
74
- from_and_to = [dest_path, "#{uri.user}@#{uri.host}:#{server.path}/#{path}"]
58
+ from_and_to = ["./#{path}", server.rsync_uri(path)]
75
59
  from_and_to.reverse! if direction == :from
76
60
  from_and_to[-1].sub! %r(/[^/]+$), '/'
77
61
 
78
62
  command = "rsync #{ssh} --delete --info=progress2 -az #{from_and_to.join(" ")}"
79
-
80
63
  Bard::Command.run! command, verbose: verbose
81
64
  end
82
65
 
83
- def rsync_as_mediator from, to
66
+ def rsync_as_mediator
84
67
  raise NotImplementedError if from.gateway || to.gateway || from.ssh_key || to.ssh_key
85
68
 
86
- dest_path = path.dup
87
- dest_path = "./#{dest_path}"
88
-
89
- from_uri = URI.parse("ssh://#{from.ssh}")
90
- from_str = "-p#{from_uri.port || 22} #{from_uri.user}@#{from_uri.host}"
91
-
92
- to_uri = URI.parse("ssh://#{to.ssh}")
93
- to_str = "#{to_uri.user}@#{to_uri.host}:#{to.path}/#{path}"
94
- to_str.sub! %r(/[^/]+$), '/'
95
-
96
- command = %(ssh -A #{from_str} 'rsync -e \"ssh -A -p#{to_uri.port || 22} -o StrictHostKeyChecking=no\" --delete --info=progress2 -az #{from.path}/#{path} #{to_str}')
69
+ from_str = "-p#{from.ssh_uri.port || 22} #{from.ssh_uri.user}@#{from.ssh_uri.host}"
70
+ to_str = to.rsync_uri(path).sub(%r(/[^/]+$), '/')
97
71
 
72
+ command = %(ssh -A #{from_str} 'rsync -e \"ssh -A -p#{to.ssh_uri.port || 22} -o StrictHostKeyChecking=no\" --delete --info=progress2 -az #{from.path}/#{path} #{to_str}')
98
73
  Bard::Command.run! command, verbose: verbose
99
74
  end
100
75
  end
data/lib/bard/git.rb CHANGED
@@ -8,10 +8,6 @@ module Bard
8
8
  ref.sub(/refs\/heads\//, '') # refs/heads/master ... we want "master"
9
9
  end
10
10
 
11
- def current_sha
12
- sha_of("HEAD")
13
- end
14
-
15
11
  def fast_forward_merge?(root, branch)
16
12
  root_head = sha_of(root)
17
13
  branch_head = sha_of(branch)
@@ -23,6 +19,8 @@ module Bard
23
19
  sha_of(branch) == sha_of("origin/#{branch}")
24
20
  end
25
21
 
22
+ private
23
+
26
24
  def sha_of ref
27
25
  `git rev-parse #{ref}`.chomp
28
26
  end
data/lib/bard/ping.rb CHANGED
@@ -9,7 +9,6 @@ module Bard
9
9
 
10
10
  def call
11
11
  server.ping.reject do |url|
12
- next true if url == false
13
12
  response = get_response_with_redirect(url) rescue nil
14
13
  response.is_a?(Net::HTTPSuccess)
15
14
  end
@@ -0,0 +1,16 @@
1
+ # apt sanity
2
+
3
+ class Bard::Provision::Apt < Bard::Provision
4
+ def call
5
+ print "Apt:"
6
+ provision_server.run! [
7
+ %(echo "\\$nrconf{restart} = \\"a\\";" | sudo tee /etc/needrestart/conf.d/90-autorestart.conf),
8
+ "sudo apt-get update -y",
9
+ "sudo apt-get upgrade -y",
10
+ "sudo apt-get install -y curl",
11
+ ].join("; "), home: true
12
+
13
+ puts " ✓"
14
+ end
15
+ end
16
+
@@ -4,25 +4,11 @@ class Bard::Provision::HTTP < Bard::Provision
4
4
  def call
5
5
  print "HTTP:"
6
6
  target_host = URI.parse(server.ping.first).host
7
- if system "curl -s --resolve #{target_host}:80:#{provision_server.ssh_uri.host} http://#{target_host} -I | grep -i \"x-powered-by: phusion passenger\""
7
+ if system "curl -s --resolve #{target_host}:80:#{provision_server.ssh_uri.host} http://#{target_host} -I | grep -i \"x-powered-by: phusion passenger\" >/dev/null 2>&1"
8
8
  puts " ✓"
9
9
  else
10
10
  puts " !!! not serving a rails app from #{provision_server.ssh_uri.host}"
11
11
  end
12
12
  end
13
-
14
- private
15
-
16
- def ssh_available? ssh_uri, port: ssh_uri.port
17
- system "nc -zv #{ssh_uri.host} #{port} 2>/dev/null"
18
- end
19
-
20
- def ssh_known_host? ssh_uri
21
- system "grep -q \"$(ssh-keyscan -t ed25519 -p#{ssh_uri.port || 22} #{ssh_uri.host} 2>/dev/null | cut -d ' ' -f 2-3)\" ~/.ssh/known_hosts"
22
- end
23
-
24
- def add_ssh_known_host! ssh_uri
25
- system "ssh-keyscan -p#{ssh_uri.port || 22} -H #{ssh_uri.host} >> ~/.ssh/known_hosts"
26
- end
27
13
  end
28
14
 
@@ -19,5 +19,3 @@ class Bard::Provision::MySQL < Bard::Provision
19
19
  end
20
20
  end
21
21
 
22
-
23
-
@@ -6,16 +6,14 @@ class Bard::Provision::Passenger < Bard::Provision
6
6
  if !http_responding?
7
7
  print " Installing nginx & Passenger,"
8
8
  provision_server.run! [
9
- %(echo "\\$nrconf{restart} = \\"a\\";" | sudo tee /etc/needrestart/conf.d/90-autorestart.conf),
10
9
  %(grep -qxF "RAILS_ENV=production" /etc/environment || echo "RAILS_ENV=production" | sudo tee -a /etc/environment),
11
10
  %(grep -qxF "EDITOR=vim" /etc/environment || echo "EDITOR=vim" | sudo tee -a /etc/environment),
12
- "sudo apt-get update -y",
13
- "sudo apt-get upgrade -y",
14
- "sudo apt-get install -y vim dirmngr gnupg apt-transport-https ca-certificates curl",
11
+ "sudo apt-get install -y vim dirmngr gnupg apt-transport-https ca-certificates",
15
12
  "curl https://oss-binaries.phusionpassenger.com/auto-software-signing-gpg-key.txt | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/phusion.gpg >/dev/null",
16
13
  %(echo "deb https://oss-binaries.phusionpassenger.com/apt/passenger jammy main" | sudo tee /etc/apt/sources.list.d/passenger.list),
17
14
  "sudo apt-get update -y",
18
15
  "sudo apt-get install -y nginx libnginx-mod-http-passenger",
16
+ "sudo rm /etc/nginx/sites-enabled/default",
19
17
  ].join("; "), home: true
20
18
  end
21
19
 
@@ -37,9 +37,9 @@ class Bard::Provision::Repo < Bard::Provision
37
37
  github_url = "git@github.com:botandrosedesign/#{project_name}"
38
38
  provision_server.run [
39
39
  "needle=$(ssh-keyscan -t ed25519 github.com 2>/dev/null | cut -d \" \" -f 2-3)",
40
- "grep -q \"$needle\" ~/.ssh/known_hosts || ssh-keyscan -H github.com >> ~/.ssh/known_hosts",
40
+ "grep -q \"$needle\" ~/.ssh/known_hosts || ssh-keyscan -H github.com >> ~/.ssh/known_hosts 2>/dev/null",
41
41
  "git ls-remote #{github_url}",
42
- ].join("; "), home: true
42
+ ].join("; "), home: true, quiet: true
43
43
  end
44
44
 
45
45
  def project_name
@@ -10,8 +10,9 @@ class Bard::Provision::RVM < Bard::Provision
10
10
  "gpg --keyserver keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB",
11
11
  "curl -sSL https://get.rvm.io | bash -s stable",
12
12
  ].join("; ")
13
- print " Installing Ruby #{File.read(".ruby-version")},"
14
- provision_server.run! "rvm install ."
13
+ version = File.read(".ruby-version").chomp
14
+ print " Installing Ruby #{version},"
15
+ provision_server.run! "rvm install #{version}"
15
16
  end
16
17
 
17
18
  puts " ✓"
@@ -5,16 +5,16 @@ class Bard::Provision::SSH < Bard::Provision
5
5
  def call
6
6
  print "SSH:"
7
7
 
8
- if !ssh_available?(provision_server.ssh_uri, port: server.ssh_uri.port)
8
+ if !ssh_available?(provision_server.ssh_uri, port: target_port)
9
9
  if !ssh_available?(provision_server.ssh_uri)
10
- raise "can't find SSH on port #{server.ssh_uri.port} or #{provision_server.ssh_uri.port}"
10
+ raise "can't find SSH on port #{target_port} or #{provision_server.ssh_uri.port || 22}"
11
11
  end
12
12
  if !ssh_known_host?(provision_server.ssh_uri)
13
13
  print " Adding known host,"
14
14
  add_ssh_known_host!(provision_server.ssh_uri)
15
15
  end
16
- print " Reconfiguring port to #{server.ssh_uri.port},"
17
- provision.server.run! %(echo "Port #{server.ssh_uri.port}" | sudo tee /etc/ssh/sshd_config.d/port_22022.conf; sudo service ssh restart), home: true
16
+ print " Reconfiguring port to #{target_port},"
17
+ provision_server.run! %(echo "Port #{target_port}" | sudo tee /etc/ssh/sshd_config.d/port_#{target_port}.conf; sudo service ssh restart), home: true
18
18
  end
19
19
 
20
20
  if !ssh_known_host?(provision_server.ssh_uri)
@@ -22,23 +22,30 @@ class Bard::Provision::SSH < Bard::Provision
22
22
  add_ssh_known_host!(provision_server.ssh_uri)
23
23
  end
24
24
 
25
- # provision with new port from now on
25
+ # provision with new target port from now on
26
26
  ssh_url.gsub!(/:\d+$/, "")
27
- ssh_url << ":#{server.ssh_uri.port}"
27
+ ssh_url << ":#{target_port}"
28
28
  puts " ✓"
29
29
  end
30
-
30
+
31
31
  private
32
32
 
33
- def ssh_available? ssh_uri, port: ssh_uri.port
33
+ def target_port
34
+ server.ssh_uri.port || 22
35
+ end
36
+
37
+ def ssh_available? ssh_uri, port: nil
38
+ port ||= ssh_uri.port || 22
34
39
  system "nc -zv #{ssh_uri.host} #{port} 2>/dev/null"
35
40
  end
36
41
 
37
42
  def ssh_known_host? ssh_uri
38
- system "grep -q \"$(ssh-keyscan -t ed25519 -p#{ssh_uri.port || 22} #{ssh_uri.host} 2>/dev/null | cut -d ' ' -f 2-3)\" ~/.ssh/known_hosts"
43
+ port ||= ssh_uri.port || 22
44
+ system "grep -q \"$(ssh-keyscan -t ed25519 -p#{port} #{ssh_uri.host} 2>/dev/null | cut -d ' ' -f 2-3)\" ~/.ssh/known_hosts"
39
45
  end
40
46
 
41
47
  def add_ssh_known_host! ssh_uri
42
- system "ssh-keyscan -p#{ssh_uri.port || 22} -H #{ssh_uri.host} >> ~/.ssh/known_hosts"
48
+ port ||= ssh_uri.port || 22
49
+ system "ssh-keyscan -p#{port} -H #{ssh_uri.host} >> ~/.ssh/known_hosts 2>/dev/null"
43
50
  end
44
51
  end
@@ -16,6 +16,7 @@ class Bard::Provision::User < Bard::Provision
16
16
  "sudo mkdir -p ~#{new_user}/.ssh",
17
17
  "sudo cp ~/.ssh/authorized_keys ~#{new_user}/.ssh/authorized_keys",
18
18
  "sudo chown -R #{new_user}:#{new_user} ~#{new_user}/.ssh",
19
+ "sudo chmod +rx ~#{new_user}", # so nginx and passenger can read it
19
20
  ].join("; "), home: true
20
21
  end
21
22