bard 2.0.0.beta → 2.0.1
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 +4 -4
- data/.github/workflows/ci.yml +6 -1
- data/CLAUDE.md +76 -0
- data/MIGRATION_GUIDE.md +24 -9
- data/PLUGINS.md +99 -0
- data/README.md +14 -6
- data/Rakefile +3 -1
- data/bard.gemspec +2 -1
- data/cucumber.yml +1 -0
- data/features/ci.feature +63 -0
- data/features/data.feature +13 -0
- data/features/deploy.feature +14 -0
- data/features/deploy_git_workflow.feature +89 -0
- data/features/run.feature +14 -0
- data/features/step_definitions/bard_steps.rb +136 -0
- data/features/support/bard-coverage +16 -0
- data/features/support/env.rb +14 -39
- data/features/support/test_server.rb +216 -0
- data/lib/bard/cli.rb +14 -31
- data/lib/bard/command.rb +10 -69
- data/lib/bard/config.rb +40 -183
- data/lib/bard/copy.rb +28 -103
- data/lib/bard/plugins/data.rb +56 -0
- data/lib/bard/{ci → plugins/deploy/ci}/github_actions.rb +3 -4
- data/lib/bard/plugins/deploy/ci/jenkins.rb +176 -0
- data/lib/bard/{ci → plugins/deploy/ci}/local.rb +7 -7
- data/lib/bard/{ci → plugins/deploy/ci}/runner.rb +38 -4
- data/lib/bard/plugins/deploy/ci.rb +38 -0
- data/lib/bard/plugins/deploy/ssh_strategy.rb +27 -0
- data/lib/bard/{deploy_strategy.rb → plugins/deploy/strategy.rb} +1 -1
- data/lib/bard/plugins/deploy.rb +240 -0
- data/lib/bard/{git.rb → plugins/git.rb} +6 -3
- data/lib/bard/{github.rb → plugins/github.rb} +4 -6
- data/lib/bard/{deploy_strategy/github_pages.rb → plugins/github_pages/strategy.rb} +41 -13
- data/lib/bard/plugins/github_pages.rb +30 -0
- data/lib/bard/plugins/hurt.rb +13 -0
- data/{install_files → lib/bard/plugins/install}/.github/dependabot.yml +2 -1
- data/{install_files → lib/bard/plugins/install}/.github/workflows/cache-ci.yml +1 -1
- data/{install_files → lib/bard/plugins/install}/.github/workflows/ci.yml +2 -2
- data/lib/bard/plugins/install.rb +9 -0
- data/lib/bard/plugins/open.rb +20 -0
- data/lib/bard/{ping.rb → plugins/ping/check.rb} +4 -4
- data/lib/bard/plugins/ping/target_methods.rb +23 -0
- data/lib/bard/plugins/ping.rb +10 -0
- data/lib/bard/plugins/run.rb +19 -0
- data/lib/bard/plugins/setup.rb +54 -0
- data/lib/bard/plugins/ssh/connection.rb +75 -0
- data/lib/bard/plugins/ssh/copy.rb +95 -0
- data/lib/bard/{ssh_server.rb → plugins/ssh/server.rb} +17 -42
- data/lib/bard/plugins/ssh/target_methods.rb +20 -0
- data/lib/bard/plugins/ssh.rb +10 -0
- data/lib/bard/plugins/url/target_methods.rb +23 -0
- data/lib/bard/plugins/url.rb +1 -0
- data/lib/bard/plugins/vim.rb +6 -0
- data/lib/bard/retryable.rb +25 -0
- data/lib/bard/secrets.rb +10 -0
- data/lib/bard/target.rb +27 -185
- data/lib/bard/version.rb +1 -1
- data/lib/bard.rb +1 -3
- data/spec/acceptance/docker/Dockerfile +3 -2
- data/spec/bard/capability_spec.rb +8 -50
- data/spec/bard/ci/github_actions_spec.rb +117 -14
- data/spec/bard/ci/jenkins_spec.rb +139 -0
- data/spec/bard/ci/runner_spec.rb +61 -0
- data/spec/bard/ci_spec.rb +1 -1
- data/spec/bard/cli/ci_spec.rb +34 -27
- data/spec/bard/cli/data_spec.rb +7 -26
- data/spec/bard/cli/deploy_spec.rb +87 -46
- data/spec/bard/cli/hurt_spec.rb +3 -9
- data/spec/bard/cli/install_spec.rb +5 -11
- data/spec/bard/cli/master_key_spec.rb +5 -19
- data/spec/bard/cli/open_spec.rb +14 -30
- data/spec/bard/cli/ping_spec.rb +8 -23
- data/spec/bard/cli/run_spec.rb +27 -21
- data/spec/bard/cli/setup_spec.rb +10 -27
- data/spec/bard/cli/ssh_spec.rb +10 -25
- data/spec/bard/cli/stage_spec.rb +28 -23
- data/spec/bard/cli/vim_spec.rb +3 -9
- data/spec/bard/command_spec.rb +1 -8
- data/spec/bard/config_spec.rb +78 -98
- data/spec/bard/copy_spec.rb +54 -18
- data/spec/bard/deploy_strategy/ssh_spec.rb +65 -7
- data/spec/bard/deploy_strategy_spec.rb +1 -1
- data/spec/bard/dynamic_dsl_spec.rb +18 -98
- data/spec/bard/git_spec.rb +9 -5
- data/spec/bard/github_spec.rb +2 -2
- data/spec/bard/ping_spec.rb +5 -5
- data/spec/bard/ssh_copy_spec.rb +44 -0
- data/spec/bard/ssh_server_spec.rb +8 -101
- data/spec/bard/target_spec.rb +66 -109
- data/spec/spec_helper.rb +6 -1
- metadata +79 -143
- data/README.rdoc +0 -15
- data/features/bard_check.feature +0 -94
- data/features/bard_deploy.feature +0 -18
- data/features/bard_pull.feature +0 -112
- data/features/bard_push.feature +0 -112
- data/features/podman_testcontainers.feature +0 -16
- data/features/step_definitions/check_steps.rb +0 -47
- data/features/step_definitions/git_steps.rb +0 -73
- data/features/step_definitions/global_steps.rb +0 -56
- data/features/step_definitions/podman_steps.rb +0 -23
- data/features/step_definitions/rails_steps.rb +0 -44
- data/features/step_definitions/submodule_steps.rb +0 -110
- data/features/support/grit_ext.rb +0 -13
- data/features/support/io.rb +0 -32
- data/features/support/podman.rb +0 -153
- data/lib/bard/ci/jenkins.rb +0 -105
- data/lib/bard/ci/retryable.rb +0 -27
- data/lib/bard/ci.rb +0 -50
- data/lib/bard/cli/ci.rb +0 -66
- data/lib/bard/cli/command.rb +0 -26
- data/lib/bard/cli/data.rb +0 -45
- data/lib/bard/cli/deploy.rb +0 -85
- data/lib/bard/cli/hurt.rb +0 -20
- data/lib/bard/cli/install.rb +0 -16
- data/lib/bard/cli/master_key.rb +0 -17
- data/lib/bard/cli/new.rb +0 -101
- data/lib/bard/cli/new_rails_template.rb +0 -197
- data/lib/bard/cli/open.rb +0 -22
- data/lib/bard/cli/ping.rb +0 -18
- data/lib/bard/cli/provision.rb +0 -34
- data/lib/bard/cli/run.rb +0 -24
- data/lib/bard/cli/setup.rb +0 -56
- data/lib/bard/cli/ssh.rb +0 -14
- data/lib/bard/cli/stage.rb +0 -27
- data/lib/bard/cli/vim.rb +0 -13
- data/lib/bard/default_config.rb +0 -35
- data/lib/bard/deploy_strategy/ssh.rb +0 -19
- data/lib/bard/github_pages.rb +0 -134
- data/lib/bard/provision/app.rb +0 -10
- data/lib/bard/provision/apt.rb +0 -16
- data/lib/bard/provision/authorizedkeys.rb +0 -25
- data/lib/bard/provision/data.rb +0 -27
- data/lib/bard/provision/deploy.rb +0 -10
- data/lib/bard/provision/http.rb +0 -16
- data/lib/bard/provision/logrotation.rb +0 -30
- data/lib/bard/provision/masterkey.rb +0 -18
- data/lib/bard/provision/mysql.rb +0 -22
- data/lib/bard/provision/passenger.rb +0 -37
- data/lib/bard/provision/repo.rb +0 -72
- data/lib/bard/provision/rvm.rb +0 -22
- data/lib/bard/provision/ssh.rb +0 -72
- data/lib/bard/provision/swapfile.rb +0 -21
- data/lib/bard/provision/user.rb +0 -42
- data/lib/bard/provision.rb +0 -16
- data/lib/bard/server.rb +0 -117
- data/spec/bard/cli/command_spec.rb +0 -50
- data/spec/bard/cli/new_spec.rb +0 -73
- data/spec/bard/cli/provision_spec.rb +0 -42
- data/spec/bard/github_pages_spec.rb +0 -143
- data/spec/bard/provision/app_spec.rb +0 -33
- data/spec/bard/provision/apt_spec.rb +0 -39
- data/spec/bard/provision/authorizedkeys_spec.rb +0 -40
- data/spec/bard/provision/data_spec.rb +0 -54
- data/spec/bard/provision/deploy_spec.rb +0 -33
- data/spec/bard/provision/http_spec.rb +0 -57
- data/spec/bard/provision/logrotation_spec.rb +0 -34
- data/spec/bard/provision/masterkey_spec.rb +0 -63
- data/spec/bard/provision/mysql_spec.rb +0 -55
- data/spec/bard/provision/passenger_spec.rb +0 -81
- data/spec/bard/provision/repo_spec.rb +0 -208
- data/spec/bard/provision/rvm_spec.rb +0 -49
- data/spec/bard/provision/ssh_spec.rb +0 -229
- data/spec/bard/provision/swapfile_spec.rb +0 -32
- data/spec/bard/provision/user_spec.rb +0 -103
- data/spec/bard/provision_spec.rb +0 -28
- data/spec/bard/server_spec.rb +0 -127
- /data/lib/bard/{ci → plugins/deploy/ci}/state.rb +0 -0
- /data/{install_files → lib/bard/plugins/install}/apt_dependencies.rb +0 -0
- /data/{install_files → lib/bard/plugins/install}/ci +0 -0
- /data/{install_files → lib/bard/plugins/install}/setup +0 -0
- /data/{install_files → lib/bard/plugins/install}/specified_bundler.rb +0 -0
- /data/{install_files → lib/bard/plugins/install}/specified_ruby.rb +0 -0
data/lib/bard/server.rb
DELETED
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
require "uri"
|
|
2
|
-
require "bard/command"
|
|
3
|
-
require "bard/copy"
|
|
4
|
-
|
|
5
|
-
module Bard
|
|
6
|
-
class Server < Struct.new(:project_name, :key, :ssh, :path, :ping, :gateway, :ssh_key, :env, :github_pages)
|
|
7
|
-
def self.define project_name, key, &block
|
|
8
|
-
new(project_name, key).tap do |server|
|
|
9
|
-
server.instance_eval &block
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def self.setting *fields
|
|
14
|
-
fields.each do |field|
|
|
15
|
-
define_method field do |*args|
|
|
16
|
-
if args.length == 1
|
|
17
|
-
send :"#{field}=", args.first
|
|
18
|
-
elsif args.length == 0
|
|
19
|
-
super()
|
|
20
|
-
else
|
|
21
|
-
raise ArgumentError
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
setting :ssh, :path, :ping, :gateway, :ssh_key, :env, :github_pages
|
|
28
|
-
|
|
29
|
-
def ping(*args)
|
|
30
|
-
if args.length == 0
|
|
31
|
-
(super() || [nil]).map(&method(:normalize_ping)).flatten
|
|
32
|
-
else
|
|
33
|
-
self.ping = args
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
private def normalize_ping value
|
|
38
|
-
return [] if value == false
|
|
39
|
-
normalized = "https://#{ssh_uri.host}" # default if none specified
|
|
40
|
-
if value =~ %r{^/}
|
|
41
|
-
normalized += value
|
|
42
|
-
elsif value.to_s.length > 0
|
|
43
|
-
normalized = value
|
|
44
|
-
end
|
|
45
|
-
if normalized !~ /^http/
|
|
46
|
-
normalized = "https://#{normalized}"
|
|
47
|
-
end
|
|
48
|
-
normalized
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def path(*args)
|
|
52
|
-
if args.length == 1
|
|
53
|
-
self.path = args.first
|
|
54
|
-
elsif args.length == 0
|
|
55
|
-
super() || project_name
|
|
56
|
-
else
|
|
57
|
-
raise ArgumentError
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def ssh_uri which=:ssh
|
|
62
|
-
value = send(which)
|
|
63
|
-
URI("ssh://#{value}")
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def scp_uri file_path=nil
|
|
67
|
-
ssh_uri.dup.tap do |uri|
|
|
68
|
-
uri.scheme = "scp"
|
|
69
|
-
uri.path = "/#{path}"
|
|
70
|
-
uri.path += "/#{file_path}" if file_path
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def rsync_uri file_path=nil
|
|
75
|
-
str = ssh_uri.dup.tap do |uri|
|
|
76
|
-
uri.send :set_scheme, nil
|
|
77
|
-
uri.send :set_port, nil
|
|
78
|
-
end.to_s[2..]
|
|
79
|
-
str += ":#{path}"
|
|
80
|
-
str += "/#{file_path}" if file_path
|
|
81
|
-
str
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def with(attrs)
|
|
85
|
-
dup.tap do |s|
|
|
86
|
-
attrs.each do |key, value|
|
|
87
|
-
s.send key, value
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def to_sym
|
|
93
|
-
key
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def run! command, home: false, verbose: false, quiet: false
|
|
97
|
-
Bard::Command.run! command, on: self, home:, verbose:, quiet:
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def run command, home: false, verbose: false, quiet: false
|
|
101
|
-
Bard::Command.run command, on: self, home:, verbose:, quiet:
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def exec! command, home: false
|
|
105
|
-
Bard::Command.exec! command, on: self, home:
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def copy_file path, to:, verbose: false
|
|
109
|
-
Bard::Copy.file path, from: self, to:, verbose:
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def copy_dir path, to:, verbose: false
|
|
113
|
-
Bard::Copy.dir path, from: self, to:, verbose:
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
require "bard/cli"
|
|
3
|
-
require "bard/cli/command"
|
|
4
|
-
|
|
5
|
-
class TestCommand < Bard::CLI::Command
|
|
6
|
-
desc "test_command", "test command description"
|
|
7
|
-
option :verbose, type: :boolean
|
|
8
|
-
|
|
9
|
-
def test_command
|
|
10
|
-
"executed"
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
describe Bard::CLI::Command do
|
|
15
|
-
let(:cli_mock) { double("cli") }
|
|
16
|
-
let(:command) { TestCommand.new(cli_mock) }
|
|
17
|
-
|
|
18
|
-
describe ".desc" do
|
|
19
|
-
it "sets command and description" do
|
|
20
|
-
expect(TestCommand.instance_variable_get(:@command)).to eq("test_command")
|
|
21
|
-
expect(TestCommand.instance_variable_get(:@description)).to eq("test command description")
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
describe ".option" do
|
|
26
|
-
it "sets option arguments" do
|
|
27
|
-
expect(TestCommand.instance_variable_get(:@option_args)).to eq([:verbose])
|
|
28
|
-
expect(TestCommand.instance_variable_get(:@option_kwargs)).to eq({type: :boolean})
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
describe ".setup" do
|
|
33
|
-
let(:cli_double) { double("cli") }
|
|
34
|
-
|
|
35
|
-
it "sets up the command on the CLI class" do
|
|
36
|
-
expect(cli_double).to receive(:desc).with("test_command", "test command description")
|
|
37
|
-
expect(cli_double).to receive(:option).with(:verbose, type: :boolean)
|
|
38
|
-
expect(cli_double).to receive(:define_method)
|
|
39
|
-
|
|
40
|
-
TestCommand.setup(cli_double)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
describe "delegation" do
|
|
45
|
-
it "should delegate to the wrapped object" do
|
|
46
|
-
allow(cli_mock).to receive(:some_method).and_return("delegated")
|
|
47
|
-
expect(command.some_method).to eq("delegated")
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
data/spec/bard/cli/new_spec.rb
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
require "bard/cli"
|
|
3
|
-
require "bard/cli/new"
|
|
4
|
-
|
|
5
|
-
describe Bard::CLI::New do
|
|
6
|
-
let(:new_cli) { Bard::CLI::New.new(double("cli")) }
|
|
7
|
-
|
|
8
|
-
before do
|
|
9
|
-
allow(new_cli).to receive(:puts)
|
|
10
|
-
allow(new_cli).to receive(:exit)
|
|
11
|
-
allow(new_cli).to receive(:run!)
|
|
12
|
-
allow(new_cli).to receive(:green).and_return("")
|
|
13
|
-
allow(new_cli).to receive(:red).and_return("")
|
|
14
|
-
allow(new_cli).to receive(:yellow).and_return("")
|
|
15
|
-
allow(File).to receive(:read).and_return("master_key_content")
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
describe "#new" do
|
|
19
|
-
context "with invalid project name" do
|
|
20
|
-
before do
|
|
21
|
-
allow(new_cli).to receive(:create_project)
|
|
22
|
-
allow(new_cli).to receive(:push_to_github)
|
|
23
|
-
allow(new_cli).to receive(:stage)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
it "should reject names starting with uppercase" do
|
|
27
|
-
expect(new_cli).to receive(:puts).with(/Invalid project name/)
|
|
28
|
-
expect(new_cli).to receive(:exit).with(1)
|
|
29
|
-
|
|
30
|
-
new_cli.new("InvalidProject")
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
it "should reject names with special characters" do
|
|
34
|
-
expect(new_cli).to receive(:puts).with(/Invalid project name/)
|
|
35
|
-
expect(new_cli).to receive(:exit).with(1)
|
|
36
|
-
|
|
37
|
-
new_cli.new("invalid-project")
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
it "should reject names starting with numbers" do
|
|
41
|
-
expect(new_cli).to receive(:puts).with(/Invalid project name/)
|
|
42
|
-
expect(new_cli).to receive(:exit).with(1)
|
|
43
|
-
|
|
44
|
-
new_cli.new("1invalidproject")
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
describe "#ruby_version" do
|
|
50
|
-
it "returns the ruby version" do
|
|
51
|
-
expect(new_cli.send(:ruby_version)).to eq("ruby-3.4.2")
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
describe "#template_path" do
|
|
56
|
-
it "returns the path to the rails template" do
|
|
57
|
-
expect(new_cli.send(:template_path)).to match(/new_rails_template\.rb$/)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
describe "#install_and_extract_version" do
|
|
62
|
-
it "correctly installs a gem and extracts its version", skip: !!ENV["CI"] do
|
|
63
|
-
cmd = new_cli.send :build_bash_env do
|
|
64
|
-
<<~SH
|
|
65
|
-
#{new_cli.send(:build_gem_install, "bundler", "~> 2.0")}
|
|
66
|
-
echo ${GEM_VERSION}
|
|
67
|
-
SH
|
|
68
|
-
end
|
|
69
|
-
result = `#{cmd}`.strip
|
|
70
|
-
expect(result).to match(/^2\.\d+\.\d+/)
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
end
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
require "bard/cli"
|
|
3
|
-
require "bard/cli/provision"
|
|
4
|
-
|
|
5
|
-
describe Bard::CLI::Provision do
|
|
6
|
-
let(:config) { { production: double("production", ssh: "user@example.com") } }
|
|
7
|
-
let(:provision_cli) { Bard::CLI::Provision.new(double("cli")) }
|
|
8
|
-
|
|
9
|
-
before do
|
|
10
|
-
allow(provision_cli).to receive(:config).and_return(config)
|
|
11
|
-
allow(provision_cli).to receive(:options).and_return({ steps: ["SSH", "User"] })
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
describe "STEPS constant" do
|
|
15
|
-
it "defines the provisioning steps" do
|
|
16
|
-
expect(Bard::CLI::Provision::STEPS).to include("SSH", "User", "Apt", "MySQL", "Deploy")
|
|
17
|
-
expect(Bard::CLI::Provision::STEPS).to be_a(Array)
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
describe "#provision" do
|
|
22
|
-
it "should run provision steps" do
|
|
23
|
-
expect(Bard::Provision).to receive(:const_get).with("SSH").and_return(double("ssh_step", call: true))
|
|
24
|
-
expect(Bard::Provision).to receive(:const_get).with("User").and_return(double("user_step", call: true))
|
|
25
|
-
|
|
26
|
-
provision_cli.provision
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
it "should use production ssh by default" do
|
|
30
|
-
allow(Bard::Provision).to receive(:const_get).and_return(double("step", call: true))
|
|
31
|
-
|
|
32
|
-
provision_cli.provision
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
it "should accept custom ssh_url" do
|
|
36
|
-
custom_ssh = "root@newserver.com"
|
|
37
|
-
allow(Bard::Provision).to receive(:const_get).and_return(double("step", call: true))
|
|
38
|
-
|
|
39
|
-
provision_cli.provision(custom_ssh)
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
require "bard/github_pages"
|
|
3
|
-
|
|
4
|
-
describe Bard::GithubPages do
|
|
5
|
-
let(:server) { double("server", ping: ["https://example.com"]) }
|
|
6
|
-
let(:github_pages) { Bard::GithubPages.new(double) }
|
|
7
|
-
|
|
8
|
-
before do
|
|
9
|
-
allow(Bard::Git).to receive(:sha_of).and_return("abc123")
|
|
10
|
-
allow(Bard::Git).to receive(:current_branch).and_return("main")
|
|
11
|
-
allow(github_pages).to receive(:system)
|
|
12
|
-
allow(github_pages).to receive(:run!)
|
|
13
|
-
allow(github_pages).to receive(:puts)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
describe "#deploy" do
|
|
17
|
-
it "performs the deployment steps" do
|
|
18
|
-
expect(github_pages).to receive(:build_site)
|
|
19
|
-
expect(github_pages).to receive(:create_tree_from_build).and_return("tree123")
|
|
20
|
-
expect(github_pages).to receive(:create_commit).with("tree123").and_return("commit123")
|
|
21
|
-
expect(github_pages).to receive(:commit_and_push).with("commit123")
|
|
22
|
-
|
|
23
|
-
github_pages.deploy(server)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
it "sets instance variables" do
|
|
27
|
-
allow(github_pages).to receive(:build_site)
|
|
28
|
-
allow(github_pages).to receive(:create_tree_from_build).and_return("tree123")
|
|
29
|
-
allow(github_pages).to receive(:create_commit).and_return("commit123")
|
|
30
|
-
allow(github_pages).to receive(:commit_and_push)
|
|
31
|
-
|
|
32
|
-
github_pages.deploy(server)
|
|
33
|
-
|
|
34
|
-
expect(github_pages.instance_variable_get(:@sha)).to eq("abc123")
|
|
35
|
-
expect(github_pages.instance_variable_get(:@build_dir)).to eq("tmp/github-build-abc123")
|
|
36
|
-
expect(github_pages.instance_variable_get(:@branch)).to eq("gh-pages")
|
|
37
|
-
expect(github_pages.instance_variable_get(:@domain)).to eq("example.com")
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
describe "#build_site" do
|
|
42
|
-
it "uses the locked port" do
|
|
43
|
-
github_pages.instance_variable_set(:@sha, "abc123")
|
|
44
|
-
github_pages.instance_variable_set(:@build_dir, "tmp/github-build-abc123")
|
|
45
|
-
github_pages.instance_variable_set(:@domain, "example.com")
|
|
46
|
-
|
|
47
|
-
allow(github_pages).to receive(:with_locked_port).and_yield(3005)
|
|
48
|
-
|
|
49
|
-
expect(github_pages).to receive(:run!).with(satisfy { |cmd|
|
|
50
|
-
cmd.include?("rails s -p 3005") && cmd.include?("http://localhost:3005")
|
|
51
|
-
}).ordered
|
|
52
|
-
|
|
53
|
-
expect(github_pages).to receive(:run!).with(include("kill")).ordered
|
|
54
|
-
|
|
55
|
-
github_pages.send(:build_site)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
describe "#with_locked_port" do
|
|
60
|
-
let(:file_mock) { double("file", close: true) }
|
|
61
|
-
|
|
62
|
-
before do
|
|
63
|
-
allow(File).to receive(:open).and_return(file_mock)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
it "yields the first available port" do
|
|
67
|
-
allow(file_mock).to receive(:flock).and_return(true)
|
|
68
|
-
|
|
69
|
-
expect(File).to receive(:open).with("/tmp/bard_github_pages_3000.lock", anything, anything)
|
|
70
|
-
|
|
71
|
-
yielded_port = nil
|
|
72
|
-
github_pages.send(:with_locked_port) { |p| yielded_port = p }
|
|
73
|
-
expect(yielded_port).to eq(3000)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
it "retries if the first port is locked" do
|
|
77
|
-
# 1. Try port 3000
|
|
78
|
-
expect(File).to receive(:open).with("/tmp/bard_github_pages_3000.lock", anything, anything).ordered
|
|
79
|
-
expect(file_mock).to receive(:flock).with(File::LOCK_EX | File::LOCK_NB).and_return(false).ordered
|
|
80
|
-
expect(file_mock).to receive(:close).ordered
|
|
81
|
-
|
|
82
|
-
# 2. Try port 3001
|
|
83
|
-
expect(File).to receive(:open).with("/tmp/bard_github_pages_3001.lock", anything, anything).ordered
|
|
84
|
-
expect(file_mock).to receive(:flock).with(File::LOCK_EX | File::LOCK_NB).and_return(true).ordered
|
|
85
|
-
|
|
86
|
-
# 3. Cleanup after yielding
|
|
87
|
-
expect(file_mock).to receive(:flock).with(File::LOCK_UN).ordered
|
|
88
|
-
expect(file_mock).to receive(:close).ordered
|
|
89
|
-
|
|
90
|
-
yielded_port = nil
|
|
91
|
-
github_pages.send(:with_locked_port) { |p| yielded_port = p }
|
|
92
|
-
expect(yielded_port).to eq(3001)
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
it "raises an error if no ports are available" do
|
|
96
|
-
allow(file_mock).to receive(:flock).and_return(false)
|
|
97
|
-
|
|
98
|
-
expect {
|
|
99
|
-
github_pages.send(:with_locked_port) {}
|
|
100
|
-
}.to raise_error(/Could not find an available port/)
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
describe "#get_parent_commit" do
|
|
105
|
-
it "returns the sha of the gh-pages branch" do
|
|
106
|
-
github_pages.instance_variable_set(:@branch, "gh-pages")
|
|
107
|
-
expect(Bard::Git).to receive(:sha_of).with("gh-pages^{commit}")
|
|
108
|
-
github_pages.send(:get_parent_commit)
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
describe "#branch_exists?" do
|
|
113
|
-
it "checks if branch exists using git show-ref" do
|
|
114
|
-
github_pages.instance_variable_set(:@branch, "gh-pages")
|
|
115
|
-
expect(github_pages).to receive(:system).with("git show-ref --verify --quiet refs/heads/gh-pages")
|
|
116
|
-
github_pages.send(:branch_exists?)
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
describe "#commit_and_push" do
|
|
121
|
-
before do
|
|
122
|
-
github_pages.instance_variable_set(:@branch, "gh-pages")
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
context "when branch exists" do
|
|
126
|
-
it "updates the ref and pushes" do
|
|
127
|
-
allow(github_pages).to receive(:branch_exists?).and_return(true)
|
|
128
|
-
expect(github_pages).to receive(:run!).with("git update-ref refs/heads/gh-pages commit123")
|
|
129
|
-
expect(github_pages).to receive(:run!).with("git push -f origin gh-pages:refs/heads/gh-pages")
|
|
130
|
-
github_pages.send(:commit_and_push, "commit123")
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
context "when branch doesn't exist" do
|
|
135
|
-
it "creates the branch and pushes" do
|
|
136
|
-
allow(github_pages).to receive(:branch_exists?).and_return(false)
|
|
137
|
-
expect(github_pages).to receive(:run!).with("git branch gh-pages commit123")
|
|
138
|
-
expect(github_pages).to receive(:run!).with("git push -f origin gh-pages:refs/heads/gh-pages")
|
|
139
|
-
github_pages.send(:commit_and_push, "commit123")
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
end
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
require "bard/provision"
|
|
3
|
-
require "bard/provision/app"
|
|
4
|
-
|
|
5
|
-
describe Bard::Provision::App do
|
|
6
|
-
let(:config) { { production: double("production") } }
|
|
7
|
-
let(:ssh_url) { "user@example.com" }
|
|
8
|
-
let(:provision_server) { double("provision_server") }
|
|
9
|
-
let(:app) { Bard::Provision::App.new(config, ssh_url) }
|
|
10
|
-
|
|
11
|
-
before do
|
|
12
|
-
allow(app).to receive(:provision_server).and_return(provision_server)
|
|
13
|
-
allow(app).to receive(:print)
|
|
14
|
-
allow(app).to receive(:puts)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
describe "#call" do
|
|
18
|
-
it "runs bin/setup on the server" do
|
|
19
|
-
expect(provision_server).to receive(:run!).with("bin/setup")
|
|
20
|
-
|
|
21
|
-
app.call
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
it "prints status messages" do
|
|
25
|
-
allow(provision_server).to receive(:run!)
|
|
26
|
-
|
|
27
|
-
expect(app).to receive(:print).with("App:")
|
|
28
|
-
expect(app).to receive(:puts).with(" ✓")
|
|
29
|
-
|
|
30
|
-
app.call
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
require "bard/provision"
|
|
3
|
-
require "bard/provision/apt"
|
|
4
|
-
|
|
5
|
-
describe Bard::Provision::Apt do
|
|
6
|
-
let(:config) { { production: double("production") } }
|
|
7
|
-
let(:ssh_url) { "user@example.com" }
|
|
8
|
-
let(:provision_server) { double("provision_server") }
|
|
9
|
-
let(:apt) { Bard::Provision::Apt.new(config, ssh_url) }
|
|
10
|
-
|
|
11
|
-
before do
|
|
12
|
-
allow(apt).to receive(:provision_server).and_return(provision_server)
|
|
13
|
-
allow(apt).to receive(:print)
|
|
14
|
-
allow(apt).to receive(:puts)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
describe "#call" do
|
|
18
|
-
it "updates and installs packages on the server" do
|
|
19
|
-
expected_commands = [
|
|
20
|
-
%(echo "\\$nrconf{restart} = \\"a\\";" | sudo tee /etc/needrestart/conf.d/90-autorestart.conf),
|
|
21
|
-
"sudo apt-get update -y",
|
|
22
|
-
"sudo apt-get upgrade -y",
|
|
23
|
-
"sudo apt-get install -y curl"
|
|
24
|
-
].join("; ")
|
|
25
|
-
|
|
26
|
-
expect(provision_server).to receive(:run!).with(expected_commands, home: true)
|
|
27
|
-
|
|
28
|
-
apt.call
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it "prints status messages" do
|
|
32
|
-
allow(provision_server).to receive(:run!)
|
|
33
|
-
expect(apt).to receive(:print).with("Apt:")
|
|
34
|
-
expect(apt).to receive(:puts).with(" ✓")
|
|
35
|
-
|
|
36
|
-
apt.call
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
require "bard/provision"
|
|
3
|
-
require "bard/provision/authorizedkeys"
|
|
4
|
-
|
|
5
|
-
describe Bard::Provision::AuthorizedKeys do
|
|
6
|
-
let(:config) { { production: double("production") } }
|
|
7
|
-
let(:ssh_url) { "user@example.com" }
|
|
8
|
-
let(:provision_server) { double("provision_server") }
|
|
9
|
-
let(:authorized_keys) { Bard::Provision::AuthorizedKeys.new(config, ssh_url) }
|
|
10
|
-
|
|
11
|
-
before do
|
|
12
|
-
allow(authorized_keys).to receive(:provision_server).and_return(provision_server)
|
|
13
|
-
allow(authorized_keys).to receive(:print)
|
|
14
|
-
allow(authorized_keys).to receive(:puts)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
describe "#call" do
|
|
18
|
-
it "adds authorized keys to the server" do
|
|
19
|
-
expect(provision_server).to receive(:run!).at_least(:once).with(/grep -F -q/, home: true)
|
|
20
|
-
|
|
21
|
-
authorized_keys.call
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
it "prints status messages" do
|
|
25
|
-
allow(provision_server).to receive(:run!)
|
|
26
|
-
expect(authorized_keys).to receive(:print).with("Authorized Keys:")
|
|
27
|
-
expect(authorized_keys).to receive(:puts).with(" ✓")
|
|
28
|
-
|
|
29
|
-
authorized_keys.call
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
describe "KEYS constant" do
|
|
34
|
-
it "should have predefined SSH keys" do
|
|
35
|
-
expect(Bard::Provision::AuthorizedKeys::KEYS).to be_a(Hash)
|
|
36
|
-
expect(Bard::Provision::AuthorizedKeys::KEYS).not_to be_empty
|
|
37
|
-
expect(Bard::Provision::AuthorizedKeys::KEYS.keys.first).to match(/@/)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
require "bard/provision"
|
|
3
|
-
require "bard/provision/data"
|
|
4
|
-
|
|
5
|
-
describe Bard::Provision::Data do
|
|
6
|
-
let(:server) { double("server", key: :production) }
|
|
7
|
-
let(:config) { double("config", data: ["uploads", "assets"]) }
|
|
8
|
-
let(:ssh_url) { "user@example.com" }
|
|
9
|
-
let(:provision_server) { double("provision_server") }
|
|
10
|
-
let(:data_provisioner) { Bard::Provision::Data.new(config, ssh_url) }
|
|
11
|
-
|
|
12
|
-
before do
|
|
13
|
-
allow(data_provisioner).to receive(:server).and_return(server)
|
|
14
|
-
allow(data_provisioner).to receive(:config).and_return(config)
|
|
15
|
-
allow(data_provisioner).to receive(:provision_server).and_return(provision_server)
|
|
16
|
-
allow(data_provisioner).to receive(:print)
|
|
17
|
-
allow(data_provisioner).to receive(:puts)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
describe "#call" do
|
|
21
|
-
it "dumps, transfers, and loads database data" do
|
|
22
|
-
expect(server).to receive(:run!).with("bin/rake db:dump")
|
|
23
|
-
expect(server).to receive(:copy_file).with("db/data.sql.gz", to: provision_server, verbose: false)
|
|
24
|
-
expect(provision_server).to receive(:run!).with("bin/rake db:load")
|
|
25
|
-
|
|
26
|
-
allow(server).to receive(:copy_dir)
|
|
27
|
-
|
|
28
|
-
data_provisioner.call
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it "synchronizes configured data directories" do
|
|
32
|
-
allow(server).to receive(:run!)
|
|
33
|
-
allow(server).to receive(:copy_file)
|
|
34
|
-
allow(provision_server).to receive(:run!)
|
|
35
|
-
|
|
36
|
-
expect(server).to receive(:copy_dir).with("uploads", to: provision_server, verbose: false)
|
|
37
|
-
expect(server).to receive(:copy_dir).with("assets", to: provision_server, verbose: false)
|
|
38
|
-
|
|
39
|
-
data_provisioner.call
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
it "prints status messages" do
|
|
43
|
-
allow(server).to receive(:run!)
|
|
44
|
-
allow(server).to receive(:copy_file)
|
|
45
|
-
allow(server).to receive(:copy_dir)
|
|
46
|
-
allow(provision_server).to receive(:run!)
|
|
47
|
-
|
|
48
|
-
expect(data_provisioner).to receive(:print).with("Data:")
|
|
49
|
-
expect(data_provisioner).to receive(:puts).with(" ✓")
|
|
50
|
-
|
|
51
|
-
data_provisioner.call
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
require "bard/provision"
|
|
3
|
-
require "bard/provision/deploy"
|
|
4
|
-
|
|
5
|
-
describe Bard::Provision::Deploy do
|
|
6
|
-
let(:config) { { production: double("production") } }
|
|
7
|
-
let(:ssh_url) { "user@example.com" }
|
|
8
|
-
let(:provision_server) { double("provision_server") }
|
|
9
|
-
let(:deploy) { Bard::Provision::Deploy.new(config, ssh_url) }
|
|
10
|
-
|
|
11
|
-
before do
|
|
12
|
-
allow(deploy).to receive(:provision_server).and_return(provision_server)
|
|
13
|
-
allow(deploy).to receive(:print)
|
|
14
|
-
allow(deploy).to receive(:puts)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
describe "#call" do
|
|
18
|
-
it "runs bin/setup on the server" do
|
|
19
|
-
expect(provision_server).to receive(:run!).with("bin/setup")
|
|
20
|
-
|
|
21
|
-
deploy.call
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
it "prints status messages" do
|
|
25
|
-
allow(provision_server).to receive(:run!)
|
|
26
|
-
|
|
27
|
-
expect(deploy).to receive(:print).with("Deploy:")
|
|
28
|
-
expect(deploy).to receive(:puts).with(" ✓")
|
|
29
|
-
|
|
30
|
-
deploy.call
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
require "bard/provision"
|
|
3
|
-
require "bard/provision/http"
|
|
4
|
-
|
|
5
|
-
describe Bard::Provision::HTTP do
|
|
6
|
-
let(:server) { double("server", ping: ["https://example.com"]) }
|
|
7
|
-
let(:config) { { production: server } }
|
|
8
|
-
let(:ssh_url) { "user@example.com" }
|
|
9
|
-
let(:provision_server) { double("provision_server") }
|
|
10
|
-
let(:http) { Bard::Provision::HTTP.new(config, ssh_url) }
|
|
11
|
-
|
|
12
|
-
before do
|
|
13
|
-
allow(http).to receive(:server).and_return(server)
|
|
14
|
-
allow(http).to receive(:provision_server).and_return(provision_server)
|
|
15
|
-
allow(provision_server).to receive_message_chain(:ssh_uri, :host).and_return("192.168.1.100")
|
|
16
|
-
allow(http).to receive(:print)
|
|
17
|
-
allow(http).to receive(:puts)
|
|
18
|
-
allow(http).to receive(:system)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
describe "#call" do
|
|
22
|
-
context "when HTTP test passes" do
|
|
23
|
-
it "shows success message" do
|
|
24
|
-
allow(http).to receive(:system).and_return(true)
|
|
25
|
-
|
|
26
|
-
expect(http).to receive(:puts).with(" ✓")
|
|
27
|
-
|
|
28
|
-
http.call
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
context "when HTTP test fails" do
|
|
33
|
-
it "shows failure message" do
|
|
34
|
-
allow(http).to receive(:system).and_return(false)
|
|
35
|
-
|
|
36
|
-
expect(http).to receive(:puts).with(" !!! not serving a rails app from 192.168.1.100")
|
|
37
|
-
|
|
38
|
-
http.call
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
it "prints status header" do
|
|
43
|
-
allow(http).to receive(:system).and_return(true)
|
|
44
|
-
|
|
45
|
-
expect(http).to receive(:print).with("HTTP:")
|
|
46
|
-
|
|
47
|
-
http.call
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
it "tests the correct URL" do
|
|
51
|
-
expected_command = /curl -s --resolve example\.com:80:192\.168\.1\.100 http:\/\/example\.com/
|
|
52
|
-
expect(http).to receive(:system).with(expected_command)
|
|
53
|
-
|
|
54
|
-
http.call
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|