bard 0.41.2 → 0.42.0

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
- SHA1:
3
- metadata.gz: b56dfecf167ffd69e2e99c558c0392fc6265f374
4
- data.tar.gz: 3e05c1a6fb673e9bd03e4ac4960ad91ed558aa22
2
+ SHA256:
3
+ metadata.gz: 8ede698ef957275736c6d373ab637f83e9a676bf3a7214a789d4314ee69f3532
4
+ data.tar.gz: c0ac00d558f50fa633858358d2387f68095810e8741b13b4227a08cfd3f9c5c4
5
5
  SHA512:
6
- metadata.gz: 3649d61bdf34b2340a1720c7b76ded57c6a0d3a015919f69d45210ed28556fe0d4efb3bed58b0cb1f34ecb4fc8c81543979cf8359afb0a00782e9a2f040cd975
7
- data.tar.gz: e6b78253e0841ddc31e503cd515d1a56202483ba5fd29320343d78d6a1df24ff572f2fe0e80b2f6dd338caa820b29ec1d14a7d90e55b4f685a681942fc9cec58
6
+ metadata.gz: a237a2cc3ddc4611486f1dfe6b14a8c282daa7656330bc0748c960f668c4e5ec213ebd7cb9b7cd0671de95476a4a61b0e6763bb5588cda63dc08ab2d0809f9f0
7
+ data.tar.gz: 6861a6cf67056c5762144eb4fafc809c3a7a1040a8213a5bcac5860bc4f33aec9d44dccd7567e761f96465b20e0f14e5fa4a45aadcd96217a47b92ac7c8ce008
data/.gitignore CHANGED
@@ -7,6 +7,7 @@ rdoc
7
7
  tmp
8
8
  .bundle
9
9
  .rvmrc
10
+ .ruby-version
10
11
  Gemfile.lock
11
12
  pkg/*
12
13
 
@@ -19,11 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency "thor", ">= 0.19.0"
22
- spec.add_dependency "capistrano", "= 2.5.10"
23
- spec.add_dependency "net-ssh", "~> 4.0"
24
22
  spec.add_dependency "rvm"
25
- spec.add_dependency "rvm-capistrano"
26
- spec.add_dependency "systemu", ">= 1.2.0"
27
23
  spec.add_dependency "term-ansicolor", ">= 1.0.3"
28
24
  spec.add_dependency "bard-rake", ">= 0.1.1"
29
25
 
@@ -2,7 +2,6 @@ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
2
  require 'ruby-debug'
3
3
  require 'grit'
4
4
  require 'spec/expectations'
5
- require 'systemu'
6
5
  gem 'sqlite3-ruby'
7
6
 
8
7
  ENV["PATH"] += ":#{File.dirname(File.expand_path(__FILE__))}/../../bin"
@@ -1,5 +1,6 @@
1
+ require "open3"
1
2
  def type(command)
2
- @status, @stdout, @stderr = systemu command, :env => @env
3
+ @stdout, @stderr, @status = Open3.capture3(@env, command)
3
4
  if ENV['DEBUG']
4
5
  puts '-' * 20
5
6
  puts "Executing command: #{command}"
@@ -1,60 +1,71 @@
1
- $:.unshift File.expand_path(File.dirname(__FILE__))
2
-
3
1
  module Bard; end
4
2
 
5
3
  require "bard/base"
6
4
  require "bard/git"
7
5
  require "bard/ci"
6
+ require "bard/data"
7
+
8
+ require "bard/config"
8
9
 
9
10
  class Bard::CLI < Thor
11
+ def initialize(*args, **kwargs, &block)
12
+ super
13
+ @config = Config.new(project_name, "bard.rb")
14
+ end
15
+
10
16
  desc "data [FROM=production, TO=local]", "copy database and assets from FROM to TO"
11
- def data(from = "production", to = "local")
12
- exec "cap _2.5.10_ data:pull ROLES=#{from}" if to == "local"
13
- exec "cap _2.5.10_ data:push ROLES=#{to}" if from == "local"
17
+ def data(from="production", to="local")
18
+ Data.new(self, from, to).call
14
19
  end
15
20
 
16
21
  method_options %w( verbose -v ) => :boolean
17
- desc "stage", "pushes current branch, and stages it"
18
- def stage
19
- unless File.read("Capfile").include?("role :production")
22
+ desc "stage [BRANCH=HEAD]", "pushes current branch, and stages it"
23
+ def stage branch=Git.current_branch
24
+ unless @config.servers.key?(:production)
20
25
  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.")
21
26
  end
22
27
 
23
- branch = Git.current_branch
24
-
25
28
  run_crucial "git push -u origin #{branch}", true
26
- run_crucial "cap _2.5.10_ stage BRANCH=#{branch}", options.verbose?
29
+ command = "git fetch && git checkout -f origin/#{branch} && bin/setup"
30
+ run_crucial ssh_command(:staging, command)
27
31
  puts green("Stage Succeeded")
28
32
 
29
- unless system("cap _2.5.10_ ping ROLES=staging >/dev/null 2>&1")
30
- puts red("Staging is now down!")
31
- end
33
+ ping :staging
32
34
  end
33
35
 
34
- method_options %w( verbose -v ) => :boolean, %w( skip-ci ) => :boolean
35
- desc "deploy [BRANCH=HEAD]", "checks that branch is a ff with master, checks with ci, and then merges into master and deploys to production, and deletes branch."
36
- def deploy branch=Git.current_branch
36
+ method_options %w[verbose -v] => :boolean, %w[skip-ci] => :boolean, %w[local-ci -l] => :boolean
37
+ 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."
38
+ def deploy to=nil
39
+ branch = Git.current_branch
40
+
37
41
  if branch == "master"
38
42
  run_crucial "git push origin master:master"
39
- invoke :ci unless options["skip-ci"]
43
+ invoke :ci, [branch], options.slice("local-ci") unless options["skip-ci"]
40
44
 
41
45
  else
42
46
  run_crucial "git fetch origin master:master"
43
47
 
44
- if not Git.fast_forward_merge? "origin/master", branch
48
+ unless Git.fast_forward_merge?("origin/master", branch)
45
49
  puts "The master branch has advanced. Attempting rebase..."
46
50
  run_crucial "git rebase origin/master"
47
51
  end
48
52
 
49
53
  run_crucial "git push -f origin #{branch}:#{branch}"
50
54
 
51
- invoke :ci unless options["skip-ci"]
55
+ invoke :ci, [branch], options.slice("local-ci") unless options["skip-ci"]
52
56
 
53
57
  run_crucial "git push origin #{branch}:master"
54
58
  run_crucial "git fetch origin master:master"
55
59
  end
56
60
 
57
- run_crucial "cap _2.5.10_ deploy", options.verbose?
61
+ if `git remote` =~ /\bgithub\b/
62
+ run_crucial "git push github"
63
+ end
64
+
65
+ to ||= @config.servers.key?(:production) ? :production : :staging
66
+
67
+ command = "git pull origin master && bin/setup"
68
+ run_crucial ssh_command(to, command)
58
69
 
59
70
  puts green("Deploy Succeeded")
60
71
 
@@ -62,26 +73,20 @@ class Bard::CLI < Thor
62
73
  puts "Deleting branch: #{branch}"
63
74
  run_crucial "git push --delete origin #{branch}"
64
75
 
65
- case Git.current_branch
66
- when branch
76
+ if branch == Git.current_branch
67
77
  run_crucial "git checkout master"
68
- run_crucial "git branch -d #{branch}"
69
- when "master"
70
- run_crucial "git branch -d #{branch}"
71
- else
72
- run_crucial "git branch -D #{branch}"
73
78
  end
74
- end
75
79
 
76
- unless system("cap _2.5.10_ ping ROLES=production >/dev/null 2>&1")
77
- puts red("Production is now down!")
80
+ run_crucial "git branch -D #{branch}"
78
81
  end
82
+
83
+ ping to
79
84
  end
80
85
 
81
- method_options %w( verbose -v ) => :boolean
86
+ method_options %w[verbose -v] => :boolean, %w[local-ci -l] => :boolean
82
87
  desc "ci [BRANCH=HEAD]", "runs ci against BRANCH"
83
88
  def ci branch=Git.current_branch
84
- ci = CI.new(project_name, `git rev-parse #{branch}`.chomp)
89
+ ci = CI.new(project_name, `git rev-parse #{branch}`.chomp, local: options["local-ci"])
85
90
  if ci.exists?
86
91
  puts "Continuous integration: starting build on #{branch}..."
87
92
 
@@ -100,9 +105,9 @@ class Bard::CLI < Thor
100
105
  if success
101
106
  puts
102
107
  puts "Continuous integration: success!"
103
- if File.exist?("coverage")
108
+ if !options["local-ci"] && File.exist?("coverage")
104
109
  puts "Downloading test coverage from CI..."
105
- run_crucial "cap _2.5.10_ download_ci_test_coverage"
110
+ download_ci_test_coverage
106
111
  end
107
112
  puts "Deploying..."
108
113
  else
@@ -132,16 +137,16 @@ class Bard::CLI < Thor
132
137
  end
133
138
  end
134
139
 
135
- method_options %w( home ) => :boolean
140
+ method_options %w[home] => :boolean
136
141
  desc "ssh [TO=production]", "logs into the specified server via SSH"
137
- def ssh to="production"
138
- if to == "gubs"
139
- command = "exec $SHELL"
140
- command = "cd Sites/#{project_name} && #{command}" unless options["home"]
141
- command = %(ssh -t gubito@gubs.pagekite.me 'bash -l -c "exec ./vagrant \\"#{command}\\""')
142
- exec command
142
+ def ssh to=:production
143
+ command = "exec $SHELL -l"
144
+ if to == "gubs" && !options["home"]
145
+ server = @config.servers[:gubs]
146
+ command = %(bash -lic "exec ./vagrant \\"cd #{server.path} && #{command}\\"")
147
+ exec ssh_command(to, command, home: true)
143
148
  else
144
- exec "cap _2.5.10_ ssh ROLES=#{to}#{" NOCD=1" if options["home"]}"
149
+ exec ssh_command(to, command, home: options["home"])
145
150
  end
146
151
  end
147
152
 
@@ -150,5 +155,39 @@ class Bard::CLI < Thor
150
155
  install_files_path = File.expand_path(File.join(__dir__, "../install_files/*"))
151
156
  system "cp #{install_files_path} bin/"
152
157
  end
158
+
159
+ desc "ping [SERVER=production]", "hits the server over http to verify that its up."
160
+ def ping server=:production
161
+ server = @config.servers[server.to_sym]
162
+ return false if server.ping == false
163
+
164
+ url = server.default_ping
165
+ if server.ping =~ %r{^/}
166
+ url += server.ping
167
+ elsif server.ping.to_s.length > 0
168
+ url = server.ping
169
+ end
170
+
171
+ command = "curl -sfL #{url} 2>&1 1>/dev/null"
172
+ unless system command
173
+ puts "#{server.to_s.capitalize} is down!"
174
+ exit 1
175
+ end
176
+ end
177
+
178
+ desc "master_key [FROM=production, TO=local]", "copy master key from FROM to TO"
179
+ def master_key from="production", to="local"
180
+ if to == "local"
181
+ copy :from, from, "config/master.key"
182
+ end
183
+ if from == "local"
184
+ copy :to, to, "config/master.key"
185
+ end
186
+ end
187
+
188
+ desc "download_ci_test_coverage", "download latest test coverage information from CI"
189
+ def download_ci_test_coverage
190
+ rsync :from, :ci, "coverage"
191
+ end
153
192
  end
154
193
 
@@ -1,28 +1,79 @@
1
1
  require "thor"
2
2
  require "term/ansicolor"
3
- require "systemu"
3
+ require "open3"
4
4
 
5
5
  class Bard::CLI < Thor
6
6
  include Term::ANSIColor
7
7
 
8
8
  private
9
9
 
10
- def fatal(message)
11
- raise red("!!! ") + message
12
- end
13
-
14
10
  def run_crucial(command, verbose = false)
15
- status, stdout, stderr = systemu command
16
- fatal "Running command: #{yellow(command)}: #{stderr}" if status.to_i.nonzero?
17
- if verbose
11
+ stdout, stderr, status = Open3.capture3(command)
12
+ failed = status.to_i.nonzero?
13
+ if verbose || failed
18
14
  $stdout.puts stdout
19
15
  $stderr.puts stderr
20
16
  end
17
+ if failed
18
+ puts red("!!! ") + "Running command failed: #{yellow(command)}"
19
+ exit 1
20
+ end
21
21
  stdout.chomp
22
22
  end
23
23
 
24
24
  def project_name
25
25
  @project_name ||= File.expand_path(".").split("/").last
26
26
  end
27
+
28
+ def ssh_command server, command, home: false
29
+ server = @config.servers[server.to_sym]
30
+ uri = URI.parse("ssh://#{server.ssh}")
31
+ command = "cd #{server.path} && #{command}" unless home
32
+ command = "ssh -tt #{"-p#{uri.port} " if uri.port}#{uri.user}@#{uri.host} '#{command}'"
33
+ if server.gateway
34
+ uri = URI.parse("ssh://#{server.gateway}")
35
+ command = "ssh -tt #{" -p#{uri.port} " if uri.port}#{uri.user}@#{uri.host} \"#{command}\""
36
+ end
37
+ command
38
+ end
39
+
40
+ def copy direction, server, path
41
+ server = @config.servers[server.to_sym]
42
+
43
+ uri = URI.parse("ssh://#{server.gateway}")
44
+ port = uri.port ? "-p#{uri.port}" : ""
45
+ gateway = server.gateway ? "-oProxyCommand='ssh #{port} #{uri.user}@#{uri.host} -W %h:%p'" : ""
46
+
47
+ uri = URI.parse("ssh://#{server.ssh}")
48
+ port = uri.port ? "-P#{uri.port}" : ""
49
+ from_and_to = [path, "#{uri.user}@#{uri.host}:#{server.path}/#{path}"]
50
+
51
+ from_and_to.reverse! if direction == :from
52
+ command = "scp #{gateway} #{port} #{from_and_to.join(" ")}"
53
+
54
+ run_crucial command
55
+ end
56
+
57
+ def rsync direction, server, path
58
+ server = @config.servers[server.to_sym]
59
+
60
+ uri = URI.parse("ssh://#{server.gateway}")
61
+ port = uri.port ? "-p#{uri.port}" : ""
62
+ gateway = server.gateway ? "-oProxyCommand=\"ssh #{port} #{uri.user}@#{uri.host} -W %h:%p\"" : ""
63
+
64
+ uri = URI.parse("ssh://#{server.ssh}")
65
+ port = uri.port ? "-p#{uri.port}" : ""
66
+ ssh = "-e'ssh #{port} #{gateway}'"
67
+
68
+ dest_path = path.dup
69
+ dest_path = "./#{dest_path}"
70
+ from_and_to = [dest_path, "#{uri.user}@#{uri.host}:#{server.path}/#{path}"]
71
+ from_and_to.reverse! if direction == :from
72
+ from_and_to[-1].sub! %r(/[^/]+$), '/'
73
+
74
+ command = "rsync #{ssh} --delete -avz #{from_and_to.join(" ")}"
75
+
76
+ run_crucial command
77
+ end
27
78
  end
28
79
 
@@ -1,69 +1,142 @@
1
+ require "json"
2
+ require "forwardable"
3
+ require "open3"
4
+
1
5
  class Bard::CLI < Thor
2
- class CI < Struct.new(:project_name, :sha)
3
- def run
4
- last_time_elapsed = get_last_time_elapsed
5
- start
6
- sleep(2) until started?
6
+ class CI
7
+ def initialize project_name, sha, local: false
8
+ @project_name = project_name
9
+ @sha = sha
10
+ @local = !!local
11
+ @runner = @local ? Local.new(project_name, sha) : Remote.new(project_name, sha)
12
+ end
7
13
 
8
- start_time = Time.new.to_i
9
- while building?
10
- elapsed_time = Time.new.to_i - start_time
11
- yield elapsed_time, last_time_elapsed
12
- sleep(2)
13
- end
14
+ attr_reader :project_name, :sha, :runner
14
15
 
15
- success?
16
+ def local?
17
+ @local
16
18
  end
17
19
 
18
- def exists?
19
- `curl -s -I #{ci_host}/?token=botandrose` =~ /\b200 OK\b/
20
- end
20
+ extend Forwardable
21
21
 
22
- def console
23
- raw = `curl -s #{ci_host}/lastBuild/console?token=botandrose`
24
- raw[%r{<pre.*?>(.+)</pre>}m, 1]
25
- end
22
+ delegate [:run, :exists?, :console, :last_response] => :runner
26
23
 
27
- attr_accessor :last_response
24
+ class Remote < Struct.new(:project_name, :sha)
25
+ def run
26
+ last_time_elapsed = get_last_time_elapsed
27
+ start
28
+ sleep(2) until started?
28
29
 
29
- private
30
+ start_time = Time.new.to_i
31
+ while building?
32
+ elapsed_time = Time.new.to_i - start_time
33
+ yield elapsed_time, last_time_elapsed
34
+ sleep(2)
35
+ end
30
36
 
31
- def get_last_time_elapsed
32
- response = `curl -s #{ci_host}/lastStableBuild/api/xml?token=botandrose`
33
- response.match(/<duration>(\d+)<\/duration>/)
34
- $1 ? $1.to_i / 1000 : nil
35
- end
37
+ success?
38
+ end
36
39
 
37
- def ci_host
38
- "http://botandrose:thecakeisalie!@ci.botandrose.com/job/#{project_name}"
39
- end
40
+ def exists?
41
+ `curl -s -I #{ci_host}/?token=botandrose` =~ /\b200 OK\b/
42
+ end
40
43
 
41
- def start
42
- command = "curl -s -I -X POST '#{ci_host}/buildWithParameters?token=botandrose&GIT_REF=#{sha}'"
43
- output = `#{command}`
44
- @queueId = output[%r{Location: .+/queue/item/(\d+)/}, 1].to_i
45
- end
44
+ def console
45
+ raw = `curl -s #{ci_host}/lastBuild/console?token=botandrose`
46
+ raw[%r{<pre.*?>(.+)</pre>}m, 1]
47
+ end
46
48
 
47
- def started?
48
- command = "curl -s -g '#{ci_host}/api/json?depth=1&tree=builds[queueId,number]'"
49
- output = `#{command}`
50
- output =~ /"queueId":#{@queueId}\b/
51
- end
49
+ attr_accessor :last_response
50
+
51
+ private
52
52
 
53
- def job_id
54
- @job_id ||= begin
55
- output = `curl -s -g '#{ci_host}/api/json?depth=1&tree=builds[queueId,number]'`
56
- output[/"number":(\d+),"queueId":#{@queueId}\b/, 1].to_i
53
+ def get_last_time_elapsed
54
+ response = `curl -s #{ci_host}/lastStableBuild/api/xml?token=botandrose`
55
+ response.match(/<duration>(\d+)<\/duration>/)
56
+ $1 ? $1.to_i / 1000 : nil
57
+ end
58
+
59
+ def ci_host
60
+ "http://botandrose:thecakeisalie!@ci.botandrose.com/job/#{project_name}"
57
61
  end
58
- end
59
62
 
60
- def building?
61
- self.last_response = `curl -s #{ci_host}/#{job_id}/api/json?tree=building,result`
62
- last_response.include? '"building":true'
63
+ def start
64
+ command = "curl -s -I -X POST '#{ci_host}/buildWithParameters?token=botandrose&GIT_REF=#{sha}'"
65
+ output = `#{command}`
66
+ @queueId = output[%r{Location: .+/queue/item/(\d+)/}, 1].to_i
67
+ end
68
+
69
+ def started?
70
+ command = "curl -s -g '#{ci_host}/api/json?depth=1&tree=builds[queueId,number]'"
71
+ output = `#{command}`
72
+ JSON.parse(output)["builds"][0]["queueId"] == @queueId
73
+ end
74
+
75
+ def job_id
76
+ @job_id ||= begin
77
+ output = `curl -s -g '#{ci_host}/api/json?depth=1&tree=builds[queueId,number]'`
78
+ output[/"number":(\d+),"queueId":#{@queueId}\b/, 1].to_i
79
+ end
80
+ end
81
+
82
+ def building?
83
+ self.last_response = `curl -s #{ci_host}/#{job_id}/api/json?tree=building,result`
84
+ if last_response.blank?
85
+ sleep(2) # retry
86
+ self.last_response = `curl -s #{ci_host}/#{job_id}/api/json?tree=building,result`
87
+ if last_response.blank?
88
+ raise "Blank response from CI twice in a row. Aborting!"
89
+ end
90
+ end
91
+ last_response.include? '"building":true'
92
+ end
93
+
94
+ def success?
95
+ last_response.include? '"result":"SUCCESS"'
96
+ end
63
97
  end
64
98
 
65
- def success?
66
- last_response.include? '"result":"SUCCESS"'
99
+ class Local < Struct.new(:project_name, :sha)
100
+ def run
101
+ start
102
+
103
+ start_time = Time.new.to_i
104
+ while building?
105
+ elapsed_time = Time.new.to_i - start_time
106
+ yield elapsed_time, nil
107
+ sleep(2)
108
+ end
109
+
110
+ @stdin.close
111
+ @console = @stdout_and_stderr.read
112
+ @stdout_and_stderr.close
113
+
114
+ success?
115
+ end
116
+
117
+ def exists?
118
+ true
119
+ end
120
+
121
+ def console
122
+ @console
123
+ end
124
+
125
+ attr_accessor :last_response
126
+
127
+ private
128
+
129
+ def start
130
+ @stdin, @stdout_and_stderr, @wait_thread = Open3.popen2e("bin/rake ci")
131
+ end
132
+
133
+ def building?
134
+ ![nil, false].include?(@wait_thread.status)
135
+ end
136
+
137
+ def success?
138
+ @wait_thread.value.success?
139
+ end
67
140
  end
68
141
  end
69
142
  end
@@ -0,0 +1,85 @@
1
+ class Bard::CLI < Thor
2
+ class Config
3
+ def initialize project_name, path
4
+ @project_name = project_name
5
+ @servers = {
6
+ local: Server.new(
7
+ project_name,
8
+ :local,
9
+ false,
10
+ "./",
11
+ false,
12
+ ),
13
+ gubs: Server.new(
14
+ project_name,
15
+ :gubs,
16
+ "gubito@gubs.pagekite.me",
17
+ "Sites/#{project_name}",
18
+ false,
19
+ ),
20
+ ci: Server.new(
21
+ project_name,
22
+ :ci,
23
+ "jenkins@ci.botandrose.com:22022",
24
+ "jobs/#{project_name}/workspace",
25
+ false,
26
+ ),
27
+ staging: Server.new(
28
+ project_name,
29
+ :staging,
30
+ "www@#{project_name}.botandrose.com:22022",
31
+ ),
32
+ }
33
+ load_local_config! path
34
+ end
35
+
36
+ attr_reader :servers
37
+
38
+ def server key, &block
39
+ @servers[key] ||= Server.new(@project_name, key)
40
+ @servers[key].instance_eval &block if block_given?
41
+ @servers[key]
42
+ end
43
+
44
+ def data *paths
45
+ if paths.length == 0
46
+ Array(@data)
47
+ else
48
+ @data = paths
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def load_local_config! path
55
+ instance_eval File.read(File.expand_path(path)) if File.exist?(path)
56
+ end
57
+
58
+ class Server < Struct.new(:project_name, :key, :ssh, :path, :ping, :gateway)
59
+ def self.setting *fields
60
+ fields.each do |field|
61
+ define_method field do |*args|
62
+ if args.length == 1
63
+ send :"#{field}=", args.first
64
+ elsif args.length == 0
65
+ super()
66
+ else
67
+ raise ArgumentError
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ setting :ssh, :path, :ping, :gateway
74
+
75
+ def default_ping
76
+ uri = URI.parse("ssh://#{ssh}")
77
+ "http://#{uri.host}"
78
+ end
79
+
80
+ def path
81
+ super || project_name
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,49 @@
1
+ class Bard::CLI < Thor
2
+ class Data < Struct.new(:bard, :from, :to)
3
+ def call
4
+ if to == "local"
5
+ data_pull_db from.to_sym
6
+ data_pull_assets from.to_sym
7
+ end
8
+ if from == "local"
9
+ data_push_db to.to_sym
10
+ data_push_assets to.to_sym
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def data_pull_db server
17
+ bard.instance_eval do
18
+ run_crucial ssh_command(server, "bin/rake db:dump && gzip -9f db/data.sql")
19
+ copy :from, server, "db/data.sql.gz"
20
+ run_crucial "gunzip -f db/data.sql.gz && bin/rake db:load"
21
+ end
22
+ end
23
+
24
+ def data_push_db server
25
+ bard.instance_eval do
26
+ run_crucial "bin/rake db:dump && gzip -9f db/data.sql"
27
+ copy :to, server, "db/data.sql.gz"
28
+ run_crucial ssh_command(server, "gunzip -f db/data.sql.gz && bin/rake db:load")
29
+ end
30
+ end
31
+
32
+ def data_pull_assets server
33
+ bard.instance_eval do
34
+ @config.data.each do |path|
35
+ rsync :from, server, path
36
+ end
37
+ end
38
+ end
39
+
40
+ def data_push_assets server
41
+ bard.instance_eval do
42
+ @config.data.each do |path|
43
+ rsync :to, server, path
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
@@ -1,4 +1,4 @@
1
1
  module Bard
2
- VERSION = "0.41.2"
2
+ VERSION = "0.42.0"
3
3
  end
4
4
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.41.2
4
+ version: 0.42.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Micah Geisel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-26 00:00:00.000000000 Z
11
+ date: 2020-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -24,34 +24,6 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.19.0
27
- - !ruby/object:Gem::Dependency
28
- name: capistrano
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - '='
32
- - !ruby/object:Gem::Version
33
- version: 2.5.10
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - '='
39
- - !ruby/object:Gem::Version
40
- version: 2.5.10
41
- - !ruby/object:Gem::Dependency
42
- name: net-ssh
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '4.0'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '4.0'
55
27
  - !ruby/object:Gem::Dependency
56
28
  name: rvm
57
29
  requirement: !ruby/object:Gem::Requirement
@@ -66,34 +38,6 @@ dependencies:
66
38
  - - ">="
67
39
  - !ruby/object:Gem::Version
68
40
  version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: rvm-capistrano
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: systemu
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: 1.2.0
90
- type: :runtime
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: 1.2.0
97
41
  - !ruby/object:Gem::Dependency
98
42
  name: term-ansicolor
99
43
  requirement: !ruby/object:Gem::Requirement
@@ -174,8 +118,6 @@ extra_rdoc_files: []
174
118
  files:
175
119
  - ".gitignore"
176
120
  - ".gitmodules"
177
- - ".ruby-gemset"
178
- - ".ruby-version"
179
121
  - Gemfile
180
122
  - LICENSE
181
123
  - README.rdoc
@@ -203,8 +145,9 @@ files:
203
145
  - install_files/specified_yarn.rb
204
146
  - lib/bard.rb
205
147
  - lib/bard/base.rb
206
- - lib/bard/capistrano.rb
207
148
  - lib/bard/ci.rb
149
+ - lib/bard/config.rb
150
+ - lib/bard/data.rb
208
151
  - lib/bard/git.rb
209
152
  - lib/bard/version.rb
210
153
  - spec/bard_spec.rb
@@ -228,8 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
228
171
  - !ruby/object:Gem::Version
229
172
  version: '0'
230
173
  requirements: []
231
- rubyforge_project:
232
- rubygems_version: 2.6.14
174
+ rubygems_version: 3.0.3
233
175
  signing_key:
234
176
  specification_version: 4
235
177
  summary: CLI to automate common development tasks.
@@ -1 +0,0 @@
1
- bard
@@ -1 +0,0 @@
1
- ruby-2.4.3
@@ -1,131 +0,0 @@
1
- require 'uri'
2
-
3
- Capistrano::Configuration.instance(:must_exist).load do
4
- require "rvm/capistrano"
5
- set :rvm_type, :user
6
- ruby_version = File.read(".ruby-version").chomp
7
- ruby_gemset = File.read(".ruby-gemset").chomp
8
- set :rvm_ruby_string, [ruby_version, ruby_gemset].join("@")
9
-
10
- set :application, File.basename(Dir.pwd)
11
-
12
- role :staging, "www@staging.botandrose.com:22022"
13
- role :ci, "jenkins@ci.botandrose.com:22022"
14
-
15
- set :asset_paths, []
16
-
17
- namespace "data" do
18
- namespace "pull" do
19
- desc "pull data"
20
- task "default" do
21
- run "cd #{application} && bundle exec rake db:dump && gzip -9f db/data.sql"
22
- transfer :down, "#{application}/db/data.sql.gz", "db/data.sql.gz"
23
- system "gunzip -f db/data.sql.gz && bundle exec rake db:load"
24
- end
25
-
26
- desc "sync the static assets"
27
- task "assets" do
28
- uri = URI.parse("ssh://#{roles[ENV['ROLES'].to_sym].first.to_s}")
29
- portopt = "-e'ssh -p#{uri.port}'" if uri.port
30
-
31
- [asset_paths].flatten.each do |path|
32
- dest_path = path.dup
33
- dest_path.sub! %r(/[^/]+$), '/'
34
- system "rsync #{portopt} --delete -avz #{uri.user}@#{uri.host}:#{application}/#{path} #{dest_path}"
35
- end
36
- end
37
- end
38
-
39
- namespace "push" do
40
- desc "push data"
41
- task "default" do
42
- system "bundle exec rake db:dump && gzip -9f db/data.sql"
43
- transfer :up, "db/data.sql.gz", "#{application}/db/data.sql.gz"
44
- run "cd #{application} && gunzip -f db/data.sql.gz && bundle exec rake db:load"
45
- end
46
-
47
- desc "sync the static assets"
48
- task "assets" do
49
- uri = URI.parse("ssh://#{roles[ENV['ROLES'].to_sym].first.to_s}")
50
- portopt = "-e'ssh -p#{uri.port}'" if uri.port
51
-
52
- [asset_paths].flatten.each do |path|
53
- dest_path = path.dup
54
- dest_path.sub! %r(/[^/]+$), '/'
55
- system "rsync #{portopt} --delete -avz #{path} #{uri.user}@#{uri.host}:#{application}/#{dest_path}"
56
- end
57
- end
58
- end
59
- end
60
-
61
- after 'data:pull', 'data:pull:assets'
62
- after 'data:push', 'data:push:assets'
63
-
64
- desc "push app to production"
65
- task :deploy do
66
- deploy_roles = roles.keys.include?(:production) ? :production : :staging
67
- ENV["ROLES"] = deploy_roles.to_s
68
- find_and_execute_task "rvm:install_ruby"
69
- system "git push github" if `git remote` =~ /\bgithub\b/
70
- run "cd #{application} && git pull origin master && bin/setup", roles: deploy_roles
71
- end
72
-
73
- desc "push app to staging"
74
- task :stage do
75
- ENV["ROLES"] = "staging"
76
- find_and_execute_task "rvm:install_ruby"
77
- branch = ENV.fetch("BRANCH")
78
- run "cd #{application} && git fetch && git checkout -f origin/#{branch} && bin/setup", :roles => :staging
79
- end
80
-
81
- desc "test app for downtime"
82
- task :ping do
83
- deploy_roles = roles.keys.include?(:production) ? :production : :staging
84
- ENV["ROLES"] = deploy_roles.to_s
85
- role_name = ENV.fetch("ROLES", "production").to_sym
86
- server_definition = roles[role_name].first
87
-
88
- url = server_definition.host
89
- if role_name == :staging && server_definition.host == "staging.botandrose.com"
90
- url = "#{application}.botandrose.com"
91
- end
92
-
93
- ping_option = server_definition.options.fetch(:ping, "")
94
- if ping_option =~ %r{^/}
95
- url += ping_option
96
- elsif ping_option.to_s.length > 0
97
- url = ping_option
98
- end
99
-
100
- command = "curl -sfL #{url} 2>&1 1>/dev/null"
101
- unless system command
102
- puts "#{role_name.to_s.capitalize} is down!"
103
- exit 1
104
- end
105
- end
106
-
107
- desc "push master key"
108
- task :push_master_key do
109
- transfer :up, "config/master.key", "#{application}/config/master.key"
110
- end
111
-
112
- desc "pull master key"
113
- task :pull_master_key do
114
- transfer :down, "#{application}/config/master.key", "config/master.key"
115
- end
116
-
117
- desc "log in via ssh"
118
- task :ssh do
119
- role = ENV['ROLES'].to_sym
120
- path = role == :ci ? "jobs/#{application}/workspace" : application
121
- uri = URI.parse("ssh://#{roles[role].first.to_s}")
122
- exec "ssh -t #{"-p#{uri.port} " if uri.port}#{uri.user}@#{uri.host} '#{"cd #{path} && " unless ENV['NOCD']}exec $SHELL -l'"
123
- end
124
-
125
- desc "download latest test coverage information from CI"
126
- task :download_ci_test_coverage do
127
- uri = URI.parse("ssh://#{roles[:staging].first}")
128
- portopt = "-e'ssh -p#{uri.port}'" if uri.port
129
- system "rsync #{portopt} --delete -avz #{uri.user}@#{uri.host}:~jenkins/jobs/#{application}/workspace/coverage ./"
130
- end
131
- end