bard 2.0.0.beta → 2.0.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.
Files changed (174) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +6 -1
  3. data/CLAUDE.md +76 -0
  4. data/MIGRATION_GUIDE.md +24 -9
  5. data/PLUGINS.md +99 -0
  6. data/README.md +14 -6
  7. data/Rakefile +3 -1
  8. data/bard.gemspec +2 -1
  9. data/cucumber.yml +1 -0
  10. data/features/ci.feature +63 -0
  11. data/features/data.feature +13 -0
  12. data/features/deploy.feature +14 -0
  13. data/features/deploy_git_workflow.feature +89 -0
  14. data/features/run.feature +14 -0
  15. data/features/step_definitions/bard_steps.rb +136 -0
  16. data/features/support/bard-coverage +16 -0
  17. data/features/support/env.rb +14 -39
  18. data/features/support/test_server.rb +216 -0
  19. data/lib/bard/cli.rb +14 -31
  20. data/lib/bard/command.rb +10 -69
  21. data/lib/bard/config.rb +40 -183
  22. data/lib/bard/copy.rb +28 -103
  23. data/lib/bard/plugins/data.rb +56 -0
  24. data/lib/bard/{ci → plugins/deploy/ci}/github_actions.rb +3 -4
  25. data/lib/bard/plugins/deploy/ci/jenkins.rb +176 -0
  26. data/lib/bard/{ci → plugins/deploy/ci}/local.rb +7 -7
  27. data/lib/bard/{ci → plugins/deploy/ci}/runner.rb +38 -4
  28. data/lib/bard/plugins/deploy/ci.rb +38 -0
  29. data/lib/bard/plugins/deploy/ssh_strategy.rb +27 -0
  30. data/lib/bard/{deploy_strategy.rb → plugins/deploy/strategy.rb} +1 -1
  31. data/lib/bard/plugins/deploy.rb +240 -0
  32. data/lib/bard/{git.rb → plugins/git.rb} +6 -3
  33. data/lib/bard/{github.rb → plugins/github.rb} +4 -6
  34. data/lib/bard/{deploy_strategy/github_pages.rb → plugins/github_pages/strategy.rb} +13 -6
  35. data/lib/bard/plugins/github_pages.rb +30 -0
  36. data/lib/bard/plugins/hurt.rb +13 -0
  37. data/{install_files → lib/bard/plugins/install}/.github/dependabot.yml +2 -1
  38. data/{install_files → lib/bard/plugins/install}/.github/workflows/cache-ci.yml +1 -1
  39. data/{install_files → lib/bard/plugins/install}/.github/workflows/ci.yml +2 -2
  40. data/lib/bard/plugins/install.rb +9 -0
  41. data/lib/bard/plugins/open.rb +20 -0
  42. data/lib/bard/{ping.rb → plugins/ping/check.rb} +4 -4
  43. data/lib/bard/plugins/ping/target_methods.rb +23 -0
  44. data/lib/bard/plugins/ping.rb +10 -0
  45. data/lib/bard/plugins/run.rb +19 -0
  46. data/lib/bard/plugins/setup.rb +54 -0
  47. data/lib/bard/plugins/ssh/connection.rb +75 -0
  48. data/lib/bard/plugins/ssh/copy.rb +95 -0
  49. data/lib/bard/{ssh_server.rb → plugins/ssh/server.rb} +17 -42
  50. data/lib/bard/plugins/ssh/target_methods.rb +20 -0
  51. data/lib/bard/plugins/ssh.rb +10 -0
  52. data/lib/bard/plugins/url/target_methods.rb +23 -0
  53. data/lib/bard/plugins/url.rb +1 -0
  54. data/lib/bard/plugins/vim.rb +6 -0
  55. data/lib/bard/retryable.rb +25 -0
  56. data/lib/bard/secrets.rb +10 -0
  57. data/lib/bard/target.rb +27 -185
  58. data/lib/bard/version.rb +1 -1
  59. data/lib/bard.rb +1 -3
  60. data/spec/acceptance/docker/Dockerfile +3 -2
  61. data/spec/bard/capability_spec.rb +8 -50
  62. data/spec/bard/ci/github_actions_spec.rb +117 -14
  63. data/spec/bard/ci/jenkins_spec.rb +139 -0
  64. data/spec/bard/ci/runner_spec.rb +61 -0
  65. data/spec/bard/ci_spec.rb +1 -1
  66. data/spec/bard/cli/ci_spec.rb +34 -27
  67. data/spec/bard/cli/data_spec.rb +7 -26
  68. data/spec/bard/cli/deploy_spec.rb +87 -46
  69. data/spec/bard/cli/hurt_spec.rb +3 -9
  70. data/spec/bard/cli/install_spec.rb +5 -11
  71. data/spec/bard/cli/master_key_spec.rb +5 -19
  72. data/spec/bard/cli/open_spec.rb +14 -30
  73. data/spec/bard/cli/ping_spec.rb +8 -23
  74. data/spec/bard/cli/run_spec.rb +27 -21
  75. data/spec/bard/cli/setup_spec.rb +10 -27
  76. data/spec/bard/cli/ssh_spec.rb +10 -25
  77. data/spec/bard/cli/stage_spec.rb +28 -23
  78. data/spec/bard/cli/vim_spec.rb +3 -9
  79. data/spec/bard/command_spec.rb +1 -8
  80. data/spec/bard/config_spec.rb +78 -98
  81. data/spec/bard/copy_spec.rb +54 -18
  82. data/spec/bard/deploy_strategy/ssh_spec.rb +65 -7
  83. data/spec/bard/deploy_strategy_spec.rb +1 -1
  84. data/spec/bard/dynamic_dsl_spec.rb +18 -98
  85. data/spec/bard/git_spec.rb +9 -5
  86. data/spec/bard/github_spec.rb +2 -2
  87. data/spec/bard/ping_spec.rb +5 -5
  88. data/spec/bard/ssh_copy_spec.rb +44 -0
  89. data/spec/bard/ssh_server_spec.rb +8 -101
  90. data/spec/bard/target_spec.rb +66 -109
  91. data/spec/spec_helper.rb +6 -1
  92. metadata +79 -143
  93. data/README.rdoc +0 -15
  94. data/features/bard_check.feature +0 -94
  95. data/features/bard_deploy.feature +0 -18
  96. data/features/bard_pull.feature +0 -112
  97. data/features/bard_push.feature +0 -112
  98. data/features/podman_testcontainers.feature +0 -16
  99. data/features/step_definitions/check_steps.rb +0 -47
  100. data/features/step_definitions/git_steps.rb +0 -73
  101. data/features/step_definitions/global_steps.rb +0 -56
  102. data/features/step_definitions/podman_steps.rb +0 -23
  103. data/features/step_definitions/rails_steps.rb +0 -44
  104. data/features/step_definitions/submodule_steps.rb +0 -110
  105. data/features/support/grit_ext.rb +0 -13
  106. data/features/support/io.rb +0 -32
  107. data/features/support/podman.rb +0 -153
  108. data/lib/bard/ci/jenkins.rb +0 -105
  109. data/lib/bard/ci/retryable.rb +0 -27
  110. data/lib/bard/ci.rb +0 -50
  111. data/lib/bard/cli/ci.rb +0 -66
  112. data/lib/bard/cli/command.rb +0 -26
  113. data/lib/bard/cli/data.rb +0 -45
  114. data/lib/bard/cli/deploy.rb +0 -85
  115. data/lib/bard/cli/hurt.rb +0 -20
  116. data/lib/bard/cli/install.rb +0 -16
  117. data/lib/bard/cli/master_key.rb +0 -17
  118. data/lib/bard/cli/new.rb +0 -101
  119. data/lib/bard/cli/new_rails_template.rb +0 -197
  120. data/lib/bard/cli/open.rb +0 -22
  121. data/lib/bard/cli/ping.rb +0 -18
  122. data/lib/bard/cli/provision.rb +0 -34
  123. data/lib/bard/cli/run.rb +0 -24
  124. data/lib/bard/cli/setup.rb +0 -56
  125. data/lib/bard/cli/ssh.rb +0 -14
  126. data/lib/bard/cli/stage.rb +0 -27
  127. data/lib/bard/cli/vim.rb +0 -13
  128. data/lib/bard/default_config.rb +0 -35
  129. data/lib/bard/deploy_strategy/ssh.rb +0 -19
  130. data/lib/bard/github_pages.rb +0 -134
  131. data/lib/bard/provision/app.rb +0 -10
  132. data/lib/bard/provision/apt.rb +0 -16
  133. data/lib/bard/provision/authorizedkeys.rb +0 -25
  134. data/lib/bard/provision/data.rb +0 -27
  135. data/lib/bard/provision/deploy.rb +0 -10
  136. data/lib/bard/provision/http.rb +0 -16
  137. data/lib/bard/provision/logrotation.rb +0 -30
  138. data/lib/bard/provision/masterkey.rb +0 -18
  139. data/lib/bard/provision/mysql.rb +0 -22
  140. data/lib/bard/provision/passenger.rb +0 -37
  141. data/lib/bard/provision/repo.rb +0 -72
  142. data/lib/bard/provision/rvm.rb +0 -22
  143. data/lib/bard/provision/ssh.rb +0 -72
  144. data/lib/bard/provision/swapfile.rb +0 -21
  145. data/lib/bard/provision/user.rb +0 -42
  146. data/lib/bard/provision.rb +0 -16
  147. data/lib/bard/server.rb +0 -117
  148. data/spec/bard/cli/command_spec.rb +0 -50
  149. data/spec/bard/cli/new_spec.rb +0 -73
  150. data/spec/bard/cli/provision_spec.rb +0 -42
  151. data/spec/bard/github_pages_spec.rb +0 -143
  152. data/spec/bard/provision/app_spec.rb +0 -33
  153. data/spec/bard/provision/apt_spec.rb +0 -39
  154. data/spec/bard/provision/authorizedkeys_spec.rb +0 -40
  155. data/spec/bard/provision/data_spec.rb +0 -54
  156. data/spec/bard/provision/deploy_spec.rb +0 -33
  157. data/spec/bard/provision/http_spec.rb +0 -57
  158. data/spec/bard/provision/logrotation_spec.rb +0 -34
  159. data/spec/bard/provision/masterkey_spec.rb +0 -63
  160. data/spec/bard/provision/mysql_spec.rb +0 -55
  161. data/spec/bard/provision/passenger_spec.rb +0 -81
  162. data/spec/bard/provision/repo_spec.rb +0 -208
  163. data/spec/bard/provision/rvm_spec.rb +0 -49
  164. data/spec/bard/provision/ssh_spec.rb +0 -229
  165. data/spec/bard/provision/swapfile_spec.rb +0 -32
  166. data/spec/bard/provision/user_spec.rb +0 -103
  167. data/spec/bard/provision_spec.rb +0 -28
  168. data/spec/bard/server_spec.rb +0 -127
  169. /data/lib/bard/{ci → plugins/deploy/ci}/state.rb +0 -0
  170. /data/{install_files → lib/bard/plugins/install}/apt_dependencies.rb +0 -0
  171. /data/{install_files → lib/bard/plugins/install}/ci +0 -0
  172. /data/{install_files → lib/bard/plugins/install}/setup +0 -0
  173. /data/{install_files → lib/bard/plugins/install}/specified_bundler.rb +0 -0
  174. /data/{install_files → lib/bard/plugins/install}/specified_ruby.rb +0 -0
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ root = File.expand_path("../../..", __FILE__)
3
+
4
+ require "simplecov"
5
+ SimpleCov.root(root)
6
+ SimpleCov.start do
7
+ command_name "Cucumber (subprocess #{$$})"
8
+ track_files "lib/**/*.rb"
9
+ add_filter "spec/"
10
+ add_filter "features/"
11
+ coverage_dir "#{root}/coverage"
12
+ end
13
+
14
+ $LOAD_PATH.unshift("#{root}/lib")
15
+ require "bard/cli"
16
+ Bard::CLI.start ARGV
@@ -1,47 +1,22 @@
1
+ require "simplecov"
2
+ SimpleCov.start do
3
+ command_name "Cucumber"
4
+ track_files "lib/**/*.rb"
5
+ add_filter "spec/"
6
+ add_filter "features/"
7
+ end
8
+
1
9
  $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
- require 'ruby-debug'
3
- require 'grit'
4
- require 'spec/expectations'
5
- gem 'sqlite3-ruby'
10
+ require "bard"
11
+ require 'rspec/expectations'
12
+ require 'fileutils'
6
13
 
7
- ENV["PATH"] += ":#{File.dirname(File.expand_path(__FILE__))}/../../bin"
14
+ ENV["PATH"] = "#{File.dirname(File.expand_path(__FILE__))}:#{ENV['PATH']}"
8
15
  ENV["GIT_DIR"] = nil
9
16
  ENV["GIT_WORK_TREE"] = nil
10
17
  ENV["GIT_INDEX_FILE"] = nil
11
18
 
12
19
  ROOT = File.expand_path(File.dirname(__FILE__) + '/../..')
13
20
 
14
- # setup fixtures
15
- if File.exist?("/dev/shm")
16
- FileUtils.rm_rf "tmp"
17
- tmp_dir = "/dev/shm/bard_testing_tmp"
18
- FileUtils.rm_rf tmp_dir
19
- FileUtils.mkdir tmp_dir
20
- `ln -s #{tmp_dir} tmp`
21
- else
22
- FileUtils.rm_rf "tmp"
23
- FileUtils.mkdir "tmp"
24
- end
25
-
26
- Dir.chdir 'tmp' do
27
- `git clone --mirror --recursive #{ROOT}/fixtures/repo origin.git`
28
-
29
- `git clone --bare --recursive origin.git submodule_a.git`
30
- `git clone --bare --recursive origin.git submodule_b.git`
31
- %w(development_a development_b staging production).each do |env|
32
- `git clone --recursive origin.git #{env}`
33
- Dir.chdir env do
34
- FileUtils.cp "config/database.sample.yml", "config/database.yml"
35
- `grb track master`
36
- `git checkout master`
37
- unless env == "production"
38
- `grb track integration`
39
- `git checkout integration`
40
- end
41
- end
42
- end
43
- FileUtils.mkdir "fixtures"
44
- Dir.foreach "." do |file|
45
- FileUtils.mv(file, "fixtures/") unless %w(fixtures . ..).include? file
46
- end
47
- end
21
+ # Ensure tmp directory exists
22
+ FileUtils.mkdir_p(File.join(ROOT, "tmp"))
@@ -0,0 +1,216 @@
1
+ require "fileutils"
2
+ require "open3"
3
+ require "tmpdir"
4
+ require "docker-api"
5
+
6
+ module TestServerWorld
7
+ class << self
8
+ attr_accessor :server_available, :image_built
9
+ end
10
+
11
+ class PrerequisiteError < StandardError; end
12
+
13
+ def ensure_server_available
14
+ return if TestServerWorld.server_available
15
+
16
+ unless system("command -v podman >/dev/null 2>&1")
17
+ raise PrerequisiteError, "podman is not installed"
18
+ end
19
+
20
+ configure_container_socket
21
+ build_test_image
22
+ FileUtils.chmod(0o600, ssh_key_path)
23
+
24
+ TestServerWorld.server_available = true
25
+ end
26
+
27
+ def configure_container_socket
28
+ if ENV["DOCKER_HOST"]
29
+ Docker.url = ENV["DOCKER_HOST"]
30
+ return
31
+ end
32
+
33
+ socket_path = "/run/user/#{Process.uid}/podman/podman.sock"
34
+ unless File.exist?(socket_path)
35
+ system("systemctl --user start podman.socket 2>/dev/null")
36
+ sleep 2
37
+ end
38
+
39
+ unless File.exist?(socket_path)
40
+ raise PrerequisiteError, "Podman socket not available"
41
+ end
42
+
43
+ ENV["DOCKER_HOST"] = "unix://#{socket_path}"
44
+ Docker.url = ENV["DOCKER_HOST"]
45
+ end
46
+
47
+ def build_test_image
48
+ return if TestServerWorld.image_built
49
+
50
+ # Check if image already exists (e.g., pre-built in CI)
51
+ if image_exists?("bard-test-server")
52
+ TestServerWorld.image_built = true
53
+ return
54
+ end
55
+
56
+ system("podman pull ubuntu:24.04 >/dev/null 2>&1")
57
+
58
+ docker_dir = File.join(ROOT, "spec/acceptance/docker")
59
+ unless system("podman build -t bard-test-server -f #{docker_dir}/Dockerfile #{docker_dir} 2>&1")
60
+ raise PrerequisiteError, "Failed to build test image"
61
+ end
62
+
63
+ TestServerWorld.image_built = true
64
+ end
65
+
66
+ def image_exists?(name)
67
+ Docker::Image.get(name)
68
+ true
69
+ rescue Docker::Error::NotFoundError
70
+ false
71
+ end
72
+
73
+ def start_test_server
74
+ ensure_server_available
75
+
76
+ @container = Docker::Container.create(
77
+ "Image" => "localhost/bard-test-server:latest",
78
+ "ExposedPorts" => { "22/tcp" => {} },
79
+ "HostConfig" => {
80
+ "PortBindings" => { "22/tcp" => [{ "HostPort" => "" }] },
81
+ "PublishAllPorts" => true
82
+ }
83
+ )
84
+ @container.start
85
+ @container.refresh!
86
+
87
+ @ssh_port = @container.info["NetworkSettings"]["Ports"]["22/tcp"].first["HostPort"].to_i
88
+
89
+ wait_for_ssh
90
+ setup_test_directory
91
+ end
92
+
93
+ def wait_for_ssh
94
+ 30.times do
95
+ return if system(
96
+ "ssh", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null",
97
+ "-o", "ConnectTimeout=1", "-p", @ssh_port.to_s, "-i", ssh_key_path,
98
+ "deploy@localhost", "true",
99
+ out: File::NULL, err: File::NULL
100
+ )
101
+ sleep 0.5
102
+ end
103
+ raise PrerequisiteError, "SSH not ready"
104
+ end
105
+
106
+ def setup_test_directory
107
+ # Set up git repos on the remote container
108
+ run_ssh "git config --global user.email 'test@example.com'"
109
+ run_ssh "git config --global user.name 'Test User'"
110
+ run_ssh "git config --global init.defaultBranch master"
111
+ run_ssh "mkdir -p ~/repos/testproject.git"
112
+ run_ssh "cd ~/repos/testproject.git && git init --bare"
113
+ run_ssh "git clone ~/repos/testproject.git ~/testproject"
114
+ run_ssh "mkdir -p ~/testproject/bin ~/testproject/db"
115
+
116
+ # bin/setup script
117
+ run_ssh "echo '#!/bin/bash' > ~/testproject/bin/setup"
118
+ run_ssh "echo 'echo Setup complete' >> ~/testproject/bin/setup"
119
+ run_ssh "chmod +x ~/testproject/bin/setup"
120
+
121
+ # bin/rake script for db:dump and db:load
122
+ run_ssh <<~'SETUP'
123
+ cat > ~/testproject/bin/rake << 'SCRIPT'
124
+ #!/bin/bash
125
+ case "$1" in
126
+ db:dump)
127
+ echo "production data" | gzip > db/data.sql.gz
128
+ ;;
129
+ db:load)
130
+ gunzip -c db/data.sql.gz > /dev/null
131
+ echo "Data loaded"
132
+ ;;
133
+ esac
134
+ SCRIPT
135
+ SETUP
136
+ run_ssh "chmod +x ~/testproject/bin/rake"
137
+ run_ssh "cd ~/testproject && git add . && git commit -m 'Initial commit'"
138
+ run_ssh "cd ~/testproject && git push origin master"
139
+
140
+ # Set up local git repo in isolated temp directory
141
+ setup_local_git_repo
142
+ end
143
+
144
+ def setup_local_git_repo
145
+ @test_dir = Dir.mktmpdir("bard_test")
146
+ @ssh_command = "ssh -i #{ssh_key_path} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
147
+
148
+ Dir.chdir(@test_dir) do
149
+ # Clone directly into the temp directory (pass SSH command via env, not global ENV)
150
+ ssh_url = "ssh://deploy@localhost:#{@ssh_port}/home/deploy/repos/testproject.git"
151
+ system({ "GIT_SSH_COMMAND" => @ssh_command }, "git clone #{ssh_url} .", out: File::NULL, err: File::NULL)
152
+
153
+ # Configure git settings locally in this repo only
154
+ system("git config user.email 'test@example.com'", out: File::NULL, err: File::NULL)
155
+ system("git config user.name 'Test User'", out: File::NULL, err: File::NULL)
156
+ system("git config core.sshCommand '#{@ssh_command}'", out: File::NULL, err: File::NULL)
157
+
158
+ # Ensure db directory exists locally
159
+ FileUtils.mkdir_p("db")
160
+
161
+ # Write bard config in the test directory
162
+ File.write("bard.rb", <<~RUBY)
163
+ target :production do
164
+ ssh "deploy@localhost:#{@ssh_port}",
165
+ path: "testproject",
166
+ ssh_key: "#{ssh_key_path}"
167
+ ping false
168
+ end
169
+ RUBY
170
+ end
171
+ end
172
+
173
+ def run_ssh(command)
174
+ stdout, status = Open3.capture2e(
175
+ "ssh", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null",
176
+ "-p", @ssh_port.to_s, "-i", ssh_key_path,
177
+ "deploy@localhost", command
178
+ )
179
+ unless status.success?
180
+ raise PrerequisiteError, "SSH command failed: #{command}\nOutput: #{stdout}"
181
+ end
182
+ true
183
+ end
184
+
185
+ def run_bard(command)
186
+ Dir.chdir(@test_dir) do
187
+ bard_coverage = File.join(ROOT, "features/support/bard-coverage")
188
+ @stdout, @status = Open3.capture2e("#{bard_coverage} #{command}")
189
+ end
190
+ end
191
+
192
+ def ssh_key_path
193
+ File.join(ROOT, "spec/acceptance/docker/test_key")
194
+ end
195
+
196
+ def stop_test_server
197
+ return unless @container
198
+ @container.stop rescue nil
199
+ @container.delete(force: true) rescue nil
200
+ ensure
201
+ @container = nil
202
+ @ssh_port = nil
203
+ FileUtils.rm_rf(@test_dir) if @test_dir
204
+ @test_dir = nil
205
+ end
206
+ end
207
+
208
+ World(TestServerWorld)
209
+
210
+ Before("@server") do
211
+ start_test_server
212
+ end
213
+
214
+ After("@server") do
215
+ stop_test_server
216
+ end
data/lib/bard/cli.rb CHANGED
@@ -1,46 +1,27 @@
1
1
  # this file gets loaded in the CLI context, not the Rails boot context
2
2
 
3
3
  require "thor"
4
+ require "bard/version"
4
5
  require "bard/config"
5
6
  require "bard/command"
6
- require "term/ansicolor"
7
7
 
8
8
  module Bard
9
9
  class CLI < Thor
10
- include Term::ANSIColor
11
-
12
10
  class_option :verbose, type: :boolean, aliases: :v
13
11
 
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
- ping: "Ping",
26
- hurt: "Hurt",
27
- vim: "Vim",
28
- }.each do |command, klass|
29
- require "bard/cli/#{command}"
30
- include const_get(klass)
31
- end
32
-
33
- {
34
- provision: "Provision",
35
- new: "New",
36
- }.each do |command, klass|
37
- require "bard/cli/#{command}"
38
- const_get(klass).setup(self)
12
+ map "--version" => :version
13
+ desc "version", "Display version"
14
+ def version
15
+ puts Bard::VERSION
39
16
  end
40
17
 
41
18
  def self.exit_on_failure? = true
42
19
 
43
20
  no_commands do
21
+ def red(text) = "\e[31m#{text}\e[0m"
22
+ def yellow(text) = "\e[33m#{text}\e[0m"
23
+ def green(text) = "\e[32m#{text}\e[0m"
24
+
44
25
  def run!(...)
45
26
  Bard::Command.run!(...)
46
27
  rescue Bard::Command::Error => e
@@ -49,13 +30,15 @@ module Bard
49
30
  end
50
31
 
51
32
  def config
52
- @config ||= Bard::Config.new(project_name, path: "bard.rb")
33
+ @config ||= Bard::Config.current
53
34
  end
54
35
 
55
36
  def project_name
56
- @project_name ||= File.expand_path(".").split("/").last
37
+ config.project_name
57
38
  end
58
39
  end
40
+
41
+ # load plugins from bard and other gems
42
+ Gem.find_files("bard/plugins/*.rb").sort.each { |path| require path }
59
43
  end
60
44
  end
61
-
data/lib/bard/command.rb CHANGED
@@ -1,42 +1,20 @@
1
1
  require "open3"
2
2
 
3
3
  module Bard
4
- class Command < Struct.new(:command, :on, :home)
4
+ module Command
5
5
  class Error < RuntimeError; end
6
6
 
7
- def self.run! command, on: :local, home: false, verbose: false, quiet: false
8
- new(command, on, home).run! verbose:, quiet:
7
+ def self.run!(command, verbose: false, quiet: false)
8
+ result = run(command, verbose:, quiet:)
9
+ raise Error.new(command) unless result
10
+ result
9
11
  end
10
12
 
11
- def self.run command, on: :local, home: false, verbose: false, quiet: false
12
- new(command, on, home).run verbose:, quiet:
13
- end
14
-
15
- def self.exec! command, on: :local, home: false
16
- new(command, on, home).exec!
17
- end
18
-
19
- def run! verbose: false, quiet: false
20
- if !run(verbose:, quiet:)
21
- raise Error.new(full_command)
22
- end
23
- end
24
-
25
- def run verbose: false, quiet: false
26
- # no-op if server doesn't really exist
27
- if on.to_sym != :local
28
- # Check for new Target architecture
29
- if on.respond_to?(:server) && on.server.nil?
30
- return true
31
- # Check for old Server architecture
32
- elsif on.respond_to?(:ssh) && on.ssh == false
33
- return true
34
- end
35
- end
13
+ def self.run(command, verbose: false, quiet: false)
36
14
  if verbose
37
- system full_command(quiet: quiet)
15
+ system command
38
16
  else
39
- stdout, stderr, status = Open3.capture3(full_command)
17
+ stdout, stderr, status = Open3.capture3(command)
40
18
  failed = status.to_i.nonzero?
41
19
  if failed && !quiet
42
20
  $stdout.puts stdout
@@ -46,45 +24,8 @@ module Bard
46
24
  end
47
25
  end
48
26
 
49
- def exec!
50
- exec full_command
51
- end
52
-
53
- private
54
-
55
- def full_command quiet: false
56
- if on.to_sym == :local
57
- command
58
- else
59
- remote_command quiet: false
60
- end
61
- end
62
-
63
- def remote_command quiet: false
64
- # Support both new Target (with server attribute) and old Server architecture
65
- ssh_server = on.respond_to?(:server) ? on.server : on
66
-
67
- cmd = command
68
- if ssh_server.env
69
- cmd = "#{ssh_server.env} #{command}"
70
- end
71
- unless home
72
- path = on.respond_to?(:path) ? on.path : ssh_server.path
73
- cmd = "cd #{path} && #{cmd}" if path
74
- end
75
-
76
- ssh_key = ssh_server.ssh_key ? "-i #{ssh_server.ssh_key} " : ""
77
- ssh_uri = ssh_server.respond_to?(:ssh_uri) ? ssh_server.ssh_uri : ssh_server.ssh_uri(:ssh)
78
-
79
- cmd = "ssh -tt #{ssh_key} #{ssh_uri} '#{cmd}'"
80
-
81
- if ssh_server.gateway
82
- gateway_uri = ssh_server.respond_to?(:ssh_uri) ? ssh_server.gateway : ssh_server.ssh_uri(:gateway)
83
- cmd = "ssh -tt #{gateway_uri} \"#{cmd}\""
84
- end
85
-
86
- cmd += " 2>&1" if quiet
87
- cmd
27
+ def self.exec!(command)
28
+ Kernel.exec command
88
29
  end
89
30
  end
90
31
  end