bard 1.9.6 → 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 (157) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +2 -2
  3. data/CLAUDE.md +1 -1
  4. data/PLUGINS.md +31 -46
  5. data/bard.gemspec +2 -1
  6. data/features/ci.feature +1 -0
  7. data/features/data.feature +1 -0
  8. data/features/deploy.feature +1 -0
  9. data/features/deploy_git_workflow.feature +1 -0
  10. data/features/run.feature +1 -0
  11. data/features/step_definitions/bard_steps.rb +1 -0
  12. data/features/support/test_server.rb +3 -3
  13. data/lib/bard/cli.rb +9 -28
  14. data/lib/bard/command.rb +9 -88
  15. data/lib/bard/config.rb +38 -177
  16. data/lib/bard/copy.rb +28 -82
  17. data/lib/bard/plugins/data.rb +56 -0
  18. data/lib/bard/{ci → plugins/deploy/ci}/github_actions.rb +2 -2
  19. data/lib/bard/{ci → plugins/deploy/ci}/jenkins.rb +1 -1
  20. data/lib/bard/{ci → plugins/deploy/ci}/local.rb +1 -1
  21. data/lib/bard/{ci → plugins/deploy/ci}/runner.rb +3 -3
  22. data/lib/bard/{ci.rb → plugins/deploy/ci.rb} +1 -1
  23. data/lib/bard/plugins/deploy/ssh_strategy.rb +27 -0
  24. data/lib/bard/{deploy_strategy.rb → plugins/deploy/strategy.rb} +1 -4
  25. data/lib/bard/plugins/deploy.rb +240 -0
  26. data/lib/bard/{git.rb → plugins/git.rb} +6 -3
  27. data/lib/bard/{github.rb → plugins/github.rb} +2 -2
  28. data/lib/bard/{deploy_strategy/github_pages.rb → plugins/github_pages/strategy.rb} +3 -4
  29. data/lib/bard/plugins/github_pages.rb +11 -15
  30. data/lib/bard/plugins/hurt.rb +12 -4
  31. data/{install_files → lib/bard/plugins/install}/.github/dependabot.yml +2 -1
  32. data/{install_files → lib/bard/plugins/install}/.github/workflows/cache-ci.yml +1 -1
  33. data/{install_files → lib/bard/plugins/install}/.github/workflows/ci.yml +2 -2
  34. data/lib/bard/plugins/install.rb +7 -3
  35. data/lib/bard/plugins/open.rb +20 -0
  36. data/lib/bard/{ping.rb → plugins/ping/check.rb} +4 -4
  37. data/lib/bard/plugins/ping/target_methods.rb +23 -0
  38. data/lib/bard/plugins/ping.rb +8 -4
  39. data/lib/bard/plugins/run.rb +19 -0
  40. data/lib/bard/plugins/setup.rb +54 -0
  41. data/lib/bard/plugins/ssh/connection.rb +75 -0
  42. data/lib/bard/plugins/ssh/copy.rb +95 -0
  43. data/lib/bard/{ssh_server.rb → plugins/ssh/server.rb} +10 -42
  44. data/lib/bard/plugins/ssh/target_methods.rb +20 -0
  45. data/lib/bard/plugins/ssh.rb +10 -0
  46. data/lib/bard/plugins/url/target_methods.rb +23 -0
  47. data/lib/bard/plugins/url.rb +1 -0
  48. data/lib/bard/plugins/vim.rb +5 -4
  49. data/lib/bard/retryable.rb +25 -0
  50. data/lib/bard/target.rb +21 -230
  51. data/lib/bard/version.rb +1 -1
  52. data/lib/bard.rb +1 -3
  53. data/spec/acceptance/docker/Dockerfile +1 -1
  54. data/spec/bard/capability_spec.rb +8 -50
  55. data/spec/bard/ci/github_actions_spec.rb +1 -1
  56. data/spec/bard/ci/jenkins_spec.rb +1 -1
  57. data/spec/bard/ci/runner_spec.rb +3 -3
  58. data/spec/bard/ci_spec.rb +1 -1
  59. data/spec/bard/cli/ci_spec.rb +4 -23
  60. data/spec/bard/cli/data_spec.rb +7 -26
  61. data/spec/bard/cli/deploy_spec.rb +43 -40
  62. data/spec/bard/cli/hurt_spec.rb +2 -8
  63. data/spec/bard/cli/install_spec.rb +4 -10
  64. data/spec/bard/cli/master_key_spec.rb +5 -19
  65. data/spec/bard/cli/open_spec.rb +17 -35
  66. data/spec/bard/cli/ping_spec.rb +10 -25
  67. data/spec/bard/cli/run_spec.rb +10 -23
  68. data/spec/bard/cli/setup_spec.rb +10 -27
  69. data/spec/bard/cli/ssh_spec.rb +10 -25
  70. data/spec/bard/cli/stage_spec.rb +17 -32
  71. data/spec/bard/cli/vim_spec.rb +5 -11
  72. data/spec/bard/command_spec.rb +1 -10
  73. data/spec/bard/config_spec.rb +68 -116
  74. data/spec/bard/copy_spec.rb +54 -18
  75. data/spec/bard/deploy_strategy/ssh_spec.rb +65 -7
  76. data/spec/bard/deploy_strategy_spec.rb +1 -1
  77. data/spec/bard/dynamic_dsl_spec.rb +18 -98
  78. data/spec/bard/git_spec.rb +9 -5
  79. data/spec/bard/github_spec.rb +1 -1
  80. data/spec/bard/ping_spec.rb +5 -5
  81. data/spec/bard/ssh_copy_spec.rb +44 -0
  82. data/spec/bard/ssh_server_spec.rb +1 -98
  83. data/spec/bard/target_spec.rb +61 -108
  84. metadata +50 -124
  85. data/lib/bard/ci/retryable.rb +0 -27
  86. data/lib/bard/cli/ci.rb +0 -73
  87. data/lib/bard/cli/command.rb +0 -26
  88. data/lib/bard/cli/data.rb +0 -45
  89. data/lib/bard/cli/deploy.rb +0 -116
  90. data/lib/bard/cli/hurt.rb +0 -15
  91. data/lib/bard/cli/install.rb +0 -11
  92. data/lib/bard/cli/master_key.rb +0 -17
  93. data/lib/bard/cli/new.rb +0 -101
  94. data/lib/bard/cli/new_rails_template.rb +0 -197
  95. data/lib/bard/cli/open.rb +0 -18
  96. data/lib/bard/cli/ping.rb +0 -12
  97. data/lib/bard/cli/provision.rb +0 -34
  98. data/lib/bard/cli/run.rb +0 -26
  99. data/lib/bard/cli/setup.rb +0 -56
  100. data/lib/bard/cli/ssh.rb +0 -14
  101. data/lib/bard/cli/stage.rb +0 -35
  102. data/lib/bard/cli/vim.rb +0 -8
  103. data/lib/bard/default_config.rb +0 -35
  104. data/lib/bard/deploy_strategy/ssh.rb +0 -19
  105. data/lib/bard/deprecation.rb +0 -19
  106. data/lib/bard/github_pages.rb +0 -134
  107. data/lib/bard/plugin.rb +0 -100
  108. data/lib/bard/plugins/backup.rb +0 -19
  109. data/lib/bard/plugins/jenkins.rb +0 -6
  110. data/lib/bard/plugins/new.rb +0 -5
  111. data/lib/bard/plugins/provision.rb +0 -5
  112. data/lib/bard/provision/app.rb +0 -10
  113. data/lib/bard/provision/apt.rb +0 -16
  114. data/lib/bard/provision/authorizedkeys.rb +0 -25
  115. data/lib/bard/provision/data.rb +0 -27
  116. data/lib/bard/provision/deploy.rb +0 -10
  117. data/lib/bard/provision/http.rb +0 -16
  118. data/lib/bard/provision/logrotation.rb +0 -30
  119. data/lib/bard/provision/masterkey.rb +0 -18
  120. data/lib/bard/provision/mysql.rb +0 -22
  121. data/lib/bard/provision/passenger.rb +0 -37
  122. data/lib/bard/provision/repo.rb +0 -72
  123. data/lib/bard/provision/rvm.rb +0 -22
  124. data/lib/bard/provision/ssh.rb +0 -79
  125. data/lib/bard/provision/swapfile.rb +0 -23
  126. data/lib/bard/provision/user.rb +0 -42
  127. data/lib/bard/provision.rb +0 -16
  128. data/lib/bard/server.rb +0 -160
  129. data/spec/bard/cli/command_spec.rb +0 -50
  130. data/spec/bard/cli/new_spec.rb +0 -73
  131. data/spec/bard/cli/provision_spec.rb +0 -42
  132. data/spec/bard/deprecation_spec.rb +0 -281
  133. data/spec/bard/github_pages_spec.rb +0 -143
  134. data/spec/bard/plugin_spec.rb +0 -79
  135. data/spec/bard/provision/app_spec.rb +0 -33
  136. data/spec/bard/provision/apt_spec.rb +0 -39
  137. data/spec/bard/provision/authorizedkeys_spec.rb +0 -40
  138. data/spec/bard/provision/data_spec.rb +0 -54
  139. data/spec/bard/provision/deploy_spec.rb +0 -33
  140. data/spec/bard/provision/http_spec.rb +0 -57
  141. data/spec/bard/provision/logrotation_spec.rb +0 -34
  142. data/spec/bard/provision/masterkey_spec.rb +0 -63
  143. data/spec/bard/provision/mysql_spec.rb +0 -55
  144. data/spec/bard/provision/passenger_spec.rb +0 -81
  145. data/spec/bard/provision/repo_spec.rb +0 -208
  146. data/spec/bard/provision/rvm_spec.rb +0 -49
  147. data/spec/bard/provision/ssh_spec.rb +0 -242
  148. data/spec/bard/provision/swapfile_spec.rb +0 -33
  149. data/spec/bard/provision/user_spec.rb +0 -103
  150. data/spec/bard/provision_spec.rb +0 -28
  151. data/spec/bard/server_spec.rb +0 -127
  152. /data/lib/bard/{ci → plugins/deploy/ci}/state.rb +0 -0
  153. /data/{install_files → lib/bard/plugins/install}/apt_dependencies.rb +0 -0
  154. /data/{install_files → lib/bard/plugins/install}/ci +0 -0
  155. /data/{install_files → lib/bard/plugins/install}/setup +0 -0
  156. /data/{install_files → lib/bard/plugins/install}/specified_bundler.rb +0 -0
  157. /data/{install_files → lib/bard/plugins/install}/specified_ruby.rb +0 -0
@@ -1,24 +1,13 @@
1
1
  require "spec_helper"
2
2
  require "bard/cli"
3
- require "bard/cli/stage"
4
- require "thor"
5
3
 
6
- class TestStageCLI < Thor
7
- include Bard::CLI::Stage
8
-
9
- attr_reader :config
10
-
11
- def initialize
12
- super
13
- @config = nil
14
- end
15
- end
16
-
17
- describe Bard::CLI::Stage do
18
- let(:staging_server) { double("staging") }
19
- let(:servers) { { production: double("production"), staging: staging_server } }
20
- let(:config) { double("config", servers: servers) }
21
- let(:cli) { TestStageCLI.new }
4
+ describe "bard stage" do
5
+ let(:staging_strategy) { double("staging_strategy", deploy: true) }
6
+ let(:staging_server) { double("staging", deploy_strategy: :ssh, deploy_strategy_instance: staging_strategy) }
7
+ let(:production_server) { double("production") }
8
+ let(:targets) { { production: production_server, staging: staging_server } }
9
+ let(:config) { double("config", targets: targets) }
10
+ let(:cli) { Bard::CLI.new }
22
11
 
23
12
  before do
24
13
  allow(cli).to receive(:config).and_return(config)
@@ -31,6 +20,7 @@ describe Bard::CLI::Stage do
31
20
  allow(cli).to receive(:yellow).and_return("")
32
21
  allow(Bard::Git).to receive(:current_branch).and_return("main")
33
22
  allow(config).to receive(:[]).with(:staging).and_return(staging_server)
23
+ allow(config).to receive(:[]).with(:production).and_return(production_server)
34
24
  end
35
25
 
36
26
  describe "#stage" do
@@ -41,7 +31,7 @@ describe Bard::CLI::Stage do
41
31
  context "when production server is defined" do
42
32
  it "pushes branch and stages it" do
43
33
  expect(cli).to receive(:run!).with("git push -u origin main", verbose: true)
44
- expect(staging_server).to receive(:run!).with("git fetch && git checkout -f origin/main && bin/setup")
34
+ expect(staging_strategy).to receive(:deploy)
45
35
  expect(cli).to receive(:ping).with(:staging)
46
36
 
47
37
  cli.stage
@@ -49,7 +39,7 @@ describe Bard::CLI::Stage do
49
39
 
50
40
  it "accepts custom branch" do
51
41
  expect(cli).to receive(:run!).with("git push -u origin develop", verbose: true)
52
- expect(staging_server).to receive(:run!).with("git fetch && git checkout -f origin/develop && bin/setup")
42
+ expect(staging_strategy).to receive(:deploy)
53
43
 
54
44
  cli.stage("develop")
55
45
  end
@@ -57,26 +47,21 @@ describe Bard::CLI::Stage do
57
47
 
58
48
  context "when staging target has a deploy strategy" do
59
49
  let(:strategy_instance) { double("strategy") }
60
- let(:staging_server) { double("staging", deploy_strategy: :fake) }
50
+ let(:staging_server) { double("staging", deploy_strategy: :fake, deploy_strategy_instance: strategy_instance) }
61
51
 
62
- before do
63
- allow(staging_server).to receive(:respond_to?).with(:deploy_strategy).and_return(true)
64
- allow(staging_server).to receive(:deploy_strategy_instance).and_return(strategy_instance)
65
- allow(cli).to receive(:require).with("bard/deploy_strategy/fake").and_return(true)
66
- end
67
-
68
- it "uses the deploy strategy instead of SSH" do
52
+ it "uses the deploy strategy" do
69
53
  expect(cli).to receive(:run!).with("git push -u origin main", verbose: true)
70
54
  expect(strategy_instance).to receive(:deploy)
71
- expect(staging_server).not_to receive(:run!)
72
55
  expect(cli).to receive(:ping).with(:staging)
73
56
 
74
57
  cli.stage
75
58
  end
76
59
  end
77
60
 
78
- context "when production server is not defined" do
79
- let(:servers) { { staging: staging_server } }
61
+ context "when production target is equivalent to staging" do
62
+ before do
63
+ allow(config).to receive(:[]).with(:production).and_return(staging_server)
64
+ end
80
65
 
81
66
  it "raises an error" do
82
67
  expect { cli.stage }.to raise_error(Thor::Error, /bard stage.*is disabled/)
@@ -94,4 +79,4 @@ describe Bard::CLI::Stage do
94
79
  end
95
80
  end
96
81
  end
97
- end
82
+ end
@@ -1,17 +1,11 @@
1
1
  require "spec_helper"
2
2
  require "bard/cli"
3
- require "bard/cli/vim"
4
- require "thor"
5
3
 
6
- class TestVimCLI < Thor
7
- Bard::CLI::Vim.setup(self)
8
- end
9
-
10
- describe Bard::CLI::Vim do
11
- let(:cli) { TestVimCLI.new }
4
+ describe "bard vim" do
5
+ let(:cli) { Bard::CLI.new }
12
6
 
13
7
  before do
14
- allow_any_instance_of(Bard::CLI::Vim).to receive(:exec)
8
+ allow(cli).to receive(:exec)
15
9
  end
16
10
 
17
11
  describe "#vim" do
@@ -20,13 +14,13 @@ describe Bard::CLI::Vim do
20
14
  end
21
15
 
22
16
  it "should exec vim with git diff files by default" do
23
- expect_any_instance_of(Bard::CLI::Vim).to receive(:exec).with("vim -p `(git diff master --name-only; git ls-files --others --exclude-standard) | grep -v '^app/assets/images/' | grep -v '^app/assets/stylesheets/' | while read f; do [ -f \"$f\" ] && ! file -b \"$f\" | grep -q \"binary\" && echo \"$f\"; done | tac`")
17
+ expect(cli).to receive(:exec).with("vim -p `(git diff master --name-only; git ls-files --others --exclude-standard) | grep -v '^app/assets/images/' | grep -v '^app/assets/stylesheets/' | while read f; do [ -f \"$f\" ] && ! file -b \"$f\" | grep -q \"binary\" && echo \"$f\"; done | tac`")
24
18
 
25
19
  cli.vim
26
20
  end
27
21
 
28
22
  it "should exec vim with specified branch" do
29
- expect_any_instance_of(Bard::CLI::Vim).to receive(:exec).with("vim -p `(git diff develop --name-only; git ls-files --others --exclude-standard) | grep -v '^app/assets/images/' | grep -v '^app/assets/stylesheets/' | while read f; do [ -f \"$f\" ] && ! file -b \"$f\" | grep -q \"binary\" && echo \"$f\"; done | tac`")
23
+ expect(cli).to receive(:exec).with("vim -p `(git diff develop --name-only; git ls-files --others --exclude-standard) | grep -v '^app/assets/images/' | grep -v '^app/assets/stylesheets/' | while read f; do [ -f \"$f\" ] && ! file -b \"$f\" | grep -q \"binary\" && echo \"$f\"; done | tac`")
30
24
 
31
25
  cli.vim("develop")
32
26
  end
@@ -1,21 +1,12 @@
1
1
  require "spec_helper"
2
2
  require "bard/command"
3
- require "shellwords"
4
3
 
5
4
  describe Bard::Command do
6
- let(:remote) { double("remote", to_sym: :remote, ssh: true, env: nil, path: "/path/to", ssh_key: nil, ssh_uri: "user@example.com", gateway: nil) }
7
-
8
5
  describe ".run" do
9
6
  it "should run a command locally" do
10
7
  expect(Open3).to receive(:capture3).with("ls -l").and_return(["output", "", 0])
11
8
  Bard::Command.run "ls -l"
12
9
  end
13
-
14
- it "should run a command on a remote server" do
15
- expected_cmd = "ssh -tt -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR user@example.com #{Shellwords.shellescape("cd /path/to && ls -l")}"
16
- expect(Open3).to receive(:capture3).with(expected_cmd).and_return(["output", "", 0])
17
- Bard::Command.run "ls -l", on: remote
18
- end
19
10
  end
20
11
 
21
12
  describe ".run!" do
@@ -32,7 +23,7 @@ describe Bard::Command do
32
23
 
33
24
  describe ".exec!" do
34
25
  it "should exec a command locally" do
35
- expect_any_instance_of(Bard::Command).to receive(:exec).with("ls -l")
26
+ expect(Kernel).to receive(:exec).with("ls -l")
36
27
  Bard::Command.exec! "ls -l"
37
28
  end
38
29
  end
@@ -1,6 +1,51 @@
1
1
  require "bard/config"
2
+ require "bard/plugins/ssh/target_methods"
3
+ require "bard/plugins/data"
4
+ require "bard/plugins/github_pages"
2
5
 
3
6
  describe Bard::Config do
7
+ describe ".detect_project_name" do
8
+ let(:tmpdir) { Dir.mktmpdir("bard-detect-test") }
9
+ after { FileUtils.rm_rf(tmpdir) }
10
+
11
+ def init_repo(path)
12
+ FileUtils.mkdir_p(path)
13
+ Dir.chdir(path) do
14
+ system("git init -q")
15
+ system("git commit --allow-empty -q -m init")
16
+ end
17
+ end
18
+
19
+ it "returns the repo dir basename when run from the main checkout" do
20
+ repo = File.join(tmpdir, "myproject")
21
+ init_repo(repo)
22
+
23
+ Dir.chdir(repo) do
24
+ expect(described_class.detect_project_name).to eq("myproject")
25
+ end
26
+ end
27
+
28
+ it "returns the main repo basename when run from a sibling worktree" do
29
+ repo = File.join(tmpdir, "myproject")
30
+ init_repo(repo)
31
+ Dir.chdir(repo) { system("git worktree add -q ../wt-feature -b feature") }
32
+
33
+ Dir.chdir(File.join(tmpdir, "wt-feature")) do
34
+ expect(described_class.detect_project_name).to eq("myproject")
35
+ end
36
+ end
37
+
38
+ it "returns the main repo basename when run from a nested worktree" do
39
+ repo = File.join(tmpdir, "myproject")
40
+ init_repo(repo)
41
+ Dir.chdir(repo) { system("git worktree add -q tmp/worktrees/wt-feature -b feature") }
42
+
43
+ Dir.chdir(File.join(repo, "tmp/worktrees/wt-feature")) do
44
+ expect(described_class.detect_project_name).to eq("myproject")
45
+ end
46
+ end
47
+ end
48
+
4
49
  context "empty" do
5
50
  subject { described_class.new("tracker") }
6
51
 
@@ -10,15 +55,22 @@ describe Bard::Config do
10
55
  end
11
56
  end
12
57
 
13
- describe "#servers" do
14
- it "is prefilled with many servers" do
15
- expect(subject.servers.keys).to eq %i[local gubs ci staging]
58
+ describe "#targets" do
59
+ it "is prefilled with default targets" do
60
+ expect(subject.targets.keys).to eq %i[local gubs ci staging production]
61
+ end
62
+
63
+ it "creates Target instances for defaults" do
64
+ subject.targets.each_value do |target|
65
+ expect(target).to be_a(Bard::Target)
66
+ end
16
67
  end
17
68
  end
18
69
 
19
70
  describe "#[]" do
20
- it "promotes staging to production when production doesn't exist" do
71
+ it "defines a default production target equivalent to staging" do
21
72
  expect(subject[:production]).to eq subject[:staging]
73
+ expect(subject[:production]).not_to equal subject[:staging]
22
74
  end
23
75
  end
24
76
 
@@ -27,26 +79,16 @@ describe Bard::Config do
27
79
  expect(subject.data).to eq []
28
80
  end
29
81
  end
30
-
31
- describe "#backup" do
32
- it "returns a BackupConfig with bard enabled by default" do
33
- backup = subject.backup
34
- expect(backup).to be_a(Bard::BackupConfig)
35
- expect(backup.bard?).to eq true
36
- expect(backup.destinations).to be_empty
37
- end
38
- end
39
82
  end
40
83
 
41
84
  context "with production definition" do
42
85
  subject { described_class.new("tracker", source: <<~SOURCE) }
43
- server :production do
86
+ target :production do
44
87
  ssh "www@ssh.botandrose.com:22022"
45
- ping "tracker.botandrose.com"
88
+ url "tracker.botandrose.com"
46
89
  end
47
90
 
48
91
  data "public/system", "public/ckeditor"
49
- backup false
50
92
  SOURCE
51
93
 
52
94
  describe "#project_name" do
@@ -55,18 +97,18 @@ describe Bard::Config do
55
97
  end
56
98
  end
57
99
 
58
- describe "#servers" do
59
- it "contains the defined server" do
60
- expect(subject.servers.keys).to eq %i[local gubs ci staging production]
100
+ describe "#targets" do
101
+ it "contains the defined target" do
102
+ expect(subject.targets.keys).to eq %i[local gubs ci staging production]
61
103
  end
62
104
  end
63
105
 
64
- describe "#server" do
106
+ describe "#target" do
65
107
  it "can overwrite existing definition" do
66
- subject.server :staging do
108
+ subject.target :staging do
67
109
  ssh "www@tracker-staging.botandrose.com:22022"
68
110
  end
69
- expect(subject[:staging].ssh).to eq "www@tracker-staging.botandrose.com:22022"
111
+ expect(subject[:staging].server.to_s).to eq "www@tracker-staging.botandrose.com:22022"
70
112
  end
71
113
  end
72
114
 
@@ -75,89 +117,6 @@ describe Bard::Config do
75
117
  expect(subject.data).to eq ["public/system", "public/ckeditor"]
76
118
  end
77
119
  end
78
-
79
- describe "#backup" do
80
- it "returns the backup setting" do
81
- expect(subject.backup).to be_disabled
82
- end
83
- end
84
- end
85
-
86
- context "with new backup block syntax" do
87
- describe "#backup with bard directive" do
88
- subject { described_class.new("test", source: "backup { bard }") }
89
-
90
- it "returns a BackupConfig with bard enabled" do
91
- backup = subject.backup
92
- expect(backup).to be_a(Bard::BackupConfig)
93
- expect(backup.bard?).to eq true
94
- expect(backup.destinations).to be_empty
95
- expect(backup.self_managed?).to eq false
96
- end
97
- end
98
-
99
- describe "#backup with s3 directive" do
100
- subject { described_class.new("test", source: "backup { s3 :primary, path: 'bucket/path' }") }
101
-
102
- it "returns a BackupConfig with s3 destination" do
103
- backup = subject.backup
104
- expect(backup).to be_a(Bard::BackupConfig)
105
- expect(backup.bard?).to eq false
106
- expect(backup.destinations.length).to eq 1
107
- expect(backup.self_managed?).to eq true
108
-
109
- dest = backup.destinations.first
110
- expect(dest[:name]).to eq :primary
111
- expect(dest[:type]).to eq :s3
112
- expect(dest[:path]).to eq 'bucket/path'
113
- end
114
- end
115
-
116
- describe "#backup with both bard and s3 directives" do
117
- subject { described_class.new("test", source: "backup { bard; s3 :custom, path: 'bucket/path' }") }
118
-
119
- it "returns a BackupConfig with bard and s3 destination" do
120
- backup = subject.backup
121
- expect(backup).to be_a(Bard::BackupConfig)
122
- expect(backup.bard?).to eq true
123
- expect(backup.destinations.length).to eq 1
124
- expect(backup.self_managed?).to eq true
125
- end
126
- end
127
-
128
- describe "#backup with multiple s3 destinations" do
129
- subject do
130
- described_class.new("test", source: <<~SOURCE)
131
- backup do
132
- s3 :primary, path: 'bucket1/path'
133
- s3 :secondary, path: 'bucket2/path'
134
- end
135
- SOURCE
136
- end
137
-
138
- it "returns a BackupConfig with multiple destinations" do
139
- backup = subject.backup
140
- expect(backup).to be_a(Bard::BackupConfig)
141
- expect(backup.bard?).to eq false
142
- expect(backup.destinations.length).to eq 2
143
- expect(backup.self_managed?).to eq true
144
-
145
- expect(backup.destinations[0][:name]).to eq :primary
146
- expect(backup.destinations[1][:name]).to eq :secondary
147
- end
148
- end
149
- end
150
-
151
- context "with target overriding default server" do
152
- subject { described_class.new("tracker", source: <<~SOURCE) }
153
- target :staging do
154
- ssh false
155
- end
156
- SOURCE
157
-
158
- it "replaces the default Server with a Target" do
159
- expect(subject[:staging]).to be_a(Bard::Target)
160
- end
161
120
  end
162
121
 
163
122
  context "with remove_target" do
@@ -172,27 +131,20 @@ describe Bard::Config do
172
131
  staging = subject[:staging]
173
132
  expect(staging).to be_a(Bard::Target)
174
133
  expect(staging.ssh.to_s).to eq "deploy@new-host.com"
175
- expect(staging.ping).to eq ["https://new-host.com"]
134
+ expect(staging.url).to eq "https://new-host.com"
176
135
  end
177
136
  end
178
137
 
179
138
  context "with github_pages directive" do
180
139
  subject { described_class.new("test", source: "github_pages 'example.com'") }
181
140
 
182
- describe "#backup" do
183
- it "sets backup to false" do
184
- expect(subject.backup).to be_disabled
185
- end
186
- end
187
-
188
- describe "#server" do
189
- it "creates a production server with github_pages enabled" do
141
+ describe "#target" do
142
+ it "creates a production target with github_pages enabled" do
190
143
  production = subject[:production]
191
144
  expect(production).not_to be_nil
192
145
  expect(production.github_pages).to eq "example.com"
193
- expect(production.ssh).to eq false
146
+ expect(production.ssh).to be_nil
194
147
  end
195
148
  end
196
149
  end
197
150
  end
198
-
@@ -2,32 +2,68 @@ require "spec_helper"
2
2
  require "bard/copy"
3
3
 
4
4
  describe Bard::Copy do
5
- let(:production) { double("production", key: :production, scp_uri: "user@example.com:/path/to/file", rsync_uri: "user@example.com:/path/to/", gateway: nil, ssh_key: nil, port: "22", path: "/path/to") }
6
- let(:local) { double("local", key: :local) }
5
+ let(:local) { double("local", key: :local, has_capability?: false) }
6
+ let(:production) { double("production", key: :production, has_capability?: true) }
7
7
 
8
- context ".file" do
9
- it "should copy a file from a remote server to the local machine" do
10
- expect(Bard::Command).to receive(:run!).with("scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR user@example.com:/path/to/file path/to/file", verbose: false)
11
- Bard::Copy.file "path/to/file", from: production, to: local
8
+ around do |example|
9
+ original_handlers = Bard::Copy.instance_variable_get(:@handlers).dup
10
+ example.run
11
+ Bard::Copy.instance_variable_set(:@handlers, original_handlers)
12
+ end
13
+
14
+ describe "auto-registration" do
15
+ it "registers handlers via inherited hook" do
16
+ handler = Class.new(Bard::Copy) do
17
+ def self.can_handle?(from, to) = true
18
+ def file = "copied"
19
+ end
20
+
21
+ copy = handler.new("path", local, production, false)
22
+ expect(copy.file).to eq("copied")
12
23
  end
24
+ end
25
+
26
+ describe ".file" do
27
+ it "dispatches to the handler that can handle the pair" do
28
+ Class.new(Bard::Copy) do
29
+ def self.can_handle?(from, to) = true
30
+ def file = "file_copied"
31
+ end
13
32
 
14
- it "should copy a file from the local machine to a remote server" do
15
- expect(Bard::Command).to receive(:run!).with("scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR path/to/file user@example.com:/path/to/file", verbose: false)
16
- Bard::Copy.file "path/to/file", from: local, to: production
33
+ expect(Bard::Copy.file("db/data.sql.gz", from: local, to: production)).to eq("file_copied")
17
34
  end
18
35
  end
19
36
 
20
- context ".dir" do
21
- it "should copy a directory from a remote server to the local machine" do
22
- allow(production).to receive_message_chain("ssh_uri.port").and_return(22)
23
- expect(Bard::Command).to receive(:run!).with("rsync -e'ssh -p22' --delete --info=progress2 -az user@example.com:/path/to/ ./path/", verbose: false)
24
- Bard::Copy.dir "path/to", from: production, to: local
37
+ describe ".dir" do
38
+ it "dispatches to the handler that can handle the pair" do
39
+ Class.new(Bard::Copy) do
40
+ def self.can_handle?(from, to) = true
41
+ def dir = "dir_copied"
42
+ end
43
+
44
+ expect(Bard::Copy.dir("storage/", from: local, to: production)).to eq("dir_copied")
25
45
  end
46
+ end
47
+
48
+ describe ".handler_for!" do
49
+ it "raises when no handler matches" do
50
+ expect {
51
+ Bard::Copy.file("file", from: local, to: local)
52
+ }.to raise_error(/No copy handler for local -> local/)
53
+ end
54
+ end
55
+
56
+ describe "#initialize" do
57
+ it "stores path, from, to, verbose" do
58
+ handler = Class.new(Bard::Copy) do
59
+ def self.can_handle?(from, to) = true
60
+ end
26
61
 
27
- it "should copy a directory from the local machine to a remote server" do
28
- allow(production).to receive_message_chain("ssh_uri.port").and_return(22)
29
- expect(Bard::Command).to receive(:run!).with("rsync -e'ssh -p22' --delete --info=progress2 -az ./path/to user@example.com:/path/to/", verbose: false)
30
- Bard::Copy.dir "path/to", from: local, to: production
62
+ copy = handler.new("db/data.sql.gz", local, production, true)
63
+ expect(copy.path).to eq("db/data.sql.gz")
64
+ expect(copy.from).to eq(local)
65
+ expect(copy.to).to eq(production)
66
+ expect(copy.verbose).to eq(true)
31
67
  end
32
68
  end
33
69
  end
@@ -1,6 +1,6 @@
1
1
  require "spec_helper"
2
- require "bard/deploy_strategy"
3
- require "bard/deploy_strategy/ssh"
2
+ require "bard/plugins/deploy/strategy"
3
+ require "bard/plugins/deploy/ssh_strategy"
4
4
 
5
5
  describe Bard::DeployStrategy::SSH do
6
6
  let(:config) { double("config", project_name: "testapp") }
@@ -17,12 +17,12 @@ describe Bard::DeployStrategy::SSH do
17
17
  strategy_without_ssh = described_class.new(target_without_ssh)
18
18
 
19
19
  expect { strategy_without_ssh.deploy }
20
- .to raise_error(/SSH not configured/)
20
+ .to raise_error(/ssh capability not configured/)
21
21
  end
22
22
 
23
23
  it "runs git pull on remote server" do
24
24
  expect(target).to receive(:run!)
25
- .with(/git pull origin master/)
25
+ .with("git pull --ff-only origin master")
26
26
 
27
27
  allow(target).to receive(:run!).with(/bin\/setup/)
28
28
 
@@ -42,12 +42,69 @@ describe Bard::DeployStrategy::SSH do
42
42
  target.instance_variable_set(:@branch, "main")
43
43
 
44
44
  expect(target).to receive(:run!)
45
- .with(/git pull origin main/)
45
+ .with("git pull --ff-only origin main")
46
46
 
47
47
  allow(target).to receive(:run!).with(/bin\/setup/)
48
48
 
49
49
  strategy.deploy
50
50
  end
51
+
52
+ context "with force: true" do
53
+ it "force-checks-out the given branch on the remote server" do
54
+ expect(target).to receive(:run!).with("git fetch origin feature-x").ordered
55
+ expect(target).to receive(:run!).with("git checkout -f origin/feature-x").ordered
56
+
57
+ allow(target).to receive(:run!).with(/bin\/setup/)
58
+
59
+ strategy.deploy(branch: "feature-x", force: true)
60
+ end
61
+ end
62
+
63
+ context "with clone" do
64
+ let(:local_target) { double("local") }
65
+
66
+ before do
67
+ allow(config).to receive(:[]).with(:local).and_return(local_target)
68
+ allow(Bard::Copy).to receive(:file)
69
+ end
70
+
71
+ it "clones the repository" do
72
+ expect(target).to receive(:run!)
73
+ .with("git clone git@github.com:botandrosedesign/testapp /app", home: true)
74
+ allow(target).to receive(:run!).with("bin/setup")
75
+ allow(target).to receive(:run!).with("bard setup")
76
+
77
+ strategy.deploy(clone: "testapp")
78
+ end
79
+
80
+ it "copies master key from local" do
81
+ allow(target).to receive(:run!).with(/git clone/, home: true)
82
+ expect(Bard::Copy).to receive(:file)
83
+ .with("config/master.key", from: local_target, to: target)
84
+ allow(target).to receive(:run!).with("bin/setup")
85
+ allow(target).to receive(:run!).with("bard setup")
86
+
87
+ strategy.deploy(clone: "testapp")
88
+ end
89
+
90
+ it "runs bin/setup and bard setup" do
91
+ allow(target).to receive(:run!).with(/git clone/, home: true)
92
+ expect(target).to receive(:run!).with("bin/setup")
93
+ expect(target).to receive(:run!).with("bard setup")
94
+
95
+ strategy.deploy(clone: "testapp")
96
+ end
97
+
98
+ it "does not run git pull" do
99
+ allow(target).to receive(:run!).with(/git clone/, home: true)
100
+ allow(target).to receive(:run!).with("bin/setup")
101
+ allow(target).to receive(:run!).with("bard setup")
102
+
103
+ expect(target).not_to receive(:run!).with(/git pull/)
104
+
105
+ strategy.deploy(clone: "testapp")
106
+ end
107
+ end
51
108
  end
52
109
 
53
110
  describe "auto-registration" do
@@ -57,11 +114,12 @@ describe Bard::DeployStrategy::SSH do
57
114
  end
58
115
 
59
116
  describe "integration with target" do
60
- it "is enabled by ssh DSL method" do
117
+ it "is the default strategy when SSH is configured" do
118
+ require "bard/plugins/deploy"
61
119
  new_target = Bard::Target.new(:staging, config)
62
120
  new_target.ssh("deploy@staging.example.com:22")
63
121
 
64
- expect(new_target.deploy_strategy).to eq(:ssh)
122
+ expect(new_target.deploy_strategy_instance).to be_a(described_class)
65
123
  end
66
124
  end
67
125
  end
@@ -1,5 +1,5 @@
1
1
  require "spec_helper"
2
- require "bard/deploy_strategy"
2
+ require "bard/plugins/deploy/strategy"
3
3
 
4
4
  describe Bard::DeployStrategy do
5
5
  describe "auto-registration" do