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.
- 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} +13 -6
- 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/provision/http.rb
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
require "uri"
|
|
2
|
-
|
|
3
|
-
# test for existence
|
|
4
|
-
|
|
5
|
-
class Bard::Provision::HTTP < Bard::Provision
|
|
6
|
-
def call
|
|
7
|
-
print "HTTP:"
|
|
8
|
-
target_host = URI.parse(server.ping.first).host
|
|
9
|
-
if system "curl -s --resolve #{target_host}:80:#{provision_server.ssh_uri.host} http://#{target_host} -I | grep -i \"x-powered-by: phusion passenger\" >/dev/null 2>&1"
|
|
10
|
-
puts " ✓"
|
|
11
|
-
else
|
|
12
|
-
puts " !!! not serving a rails app from #{provision_server.ssh_uri.host}"
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# install log rotation if missing
|
|
2
|
-
|
|
3
|
-
class Bard::Provision::LogRotation < Bard::Provision
|
|
4
|
-
def call
|
|
5
|
-
print "Log Rotation:"
|
|
6
|
-
|
|
7
|
-
provision_server.run! <<~SH, quiet: true
|
|
8
|
-
file=/etc/logrotate.d/#{server.project_name}
|
|
9
|
-
if [ ! -f $file ]; then
|
|
10
|
-
sudo tee $file > /dev/null <<EOF
|
|
11
|
-
$(pwd)/log/*.log {
|
|
12
|
-
weekly
|
|
13
|
-
size 100M
|
|
14
|
-
missingok
|
|
15
|
-
rotate 52
|
|
16
|
-
delaycompress
|
|
17
|
-
notifempty
|
|
18
|
-
copytruncate
|
|
19
|
-
create 664 www www
|
|
20
|
-
}
|
|
21
|
-
EOF
|
|
22
|
-
fi
|
|
23
|
-
SH
|
|
24
|
-
|
|
25
|
-
puts " ✓"
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
require "bard/copy"
|
|
2
|
-
|
|
3
|
-
# copy master key if missing
|
|
4
|
-
|
|
5
|
-
class Bard::Provision::MasterKey < Bard::Provision
|
|
6
|
-
def call
|
|
7
|
-
print "Master Key:"
|
|
8
|
-
if File.exist?("config/master.key")
|
|
9
|
-
if !provision_server.run "[ -f config/master.key ]", quiet: true
|
|
10
|
-
print " Uploading config/master.key,"
|
|
11
|
-
Bard::Copy.new("config/master.key").scp_using_local(:to, provision_server)
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
puts " ✓"
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
data/lib/bard/provision/mysql.rb
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# install mysql
|
|
2
|
-
|
|
3
|
-
class Bard::Provision::MySQL < Bard::Provision
|
|
4
|
-
def call
|
|
5
|
-
print "MySQL:"
|
|
6
|
-
if !mysql_responding?
|
|
7
|
-
print " Installing,"
|
|
8
|
-
provision_server.run! [
|
|
9
|
-
"sudo apt-get install -y mysql-server",
|
|
10
|
-
%(sudo mysql -uroot -e "ALTER USER \\"'\\"root\\"'\\"@\\"'\\"localhost\\"'\\" IDENTIFIED WITH mysql_native_password BY \\"'\\"\\"'\\", \\"'\\"root\\"'\\"@\\"'\\"localhost\\"'\\" PASSWORD EXPIRE NEVER; FLUSH PRIVILEGES;"),
|
|
11
|
-
%(mysql -uroot -e "UPDATE mysql.user SET password_lifetime = NULL WHERE user = \\"'\\"root\\"'\\" AND host = \\"'\\"localhost\\"'\\";"),
|
|
12
|
-
].join("; "), home: true
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
puts " ✓"
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def mysql_responding?
|
|
19
|
-
provision_server.run "sudo systemctl is-active --quiet mysql", home: true, quiet: true
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# install nginx & passenger
|
|
2
|
-
|
|
3
|
-
class Bard::Provision::Passenger < Bard::Provision
|
|
4
|
-
def call
|
|
5
|
-
print "Passenger:"
|
|
6
|
-
if !http_responding?
|
|
7
|
-
print " Installing nginx & Passenger,"
|
|
8
|
-
provision_server.run! [
|
|
9
|
-
%(grep -qxF "RAILS_ENV=production" /etc/environment || echo "RAILS_ENV=production" | sudo tee -a /etc/environment),
|
|
10
|
-
%(grep -qxF "EDITOR=vim" /etc/environment || echo "EDITOR=vim" | sudo tee -a /etc/environment),
|
|
11
|
-
"sudo apt-get install -y vim dirmngr gnupg apt-transport-https ca-certificates",
|
|
12
|
-
"curl https://oss-binaries.phusionpassenger.com/auto-software-signing-gpg-key.txt | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/phusion.gpg >/dev/null",
|
|
13
|
-
%(echo "deb https://oss-binaries.phusionpassenger.com/apt/passenger jammy main" | sudo tee /etc/apt/sources.list.d/passenger.list),
|
|
14
|
-
"sudo apt-get update -y",
|
|
15
|
-
"sudo apt-get install -y nginx libnginx-mod-http-passenger",
|
|
16
|
-
"sudo rm /etc/nginx/sites-enabled/default",
|
|
17
|
-
].join("; "), home: true
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
if !app_configured?
|
|
21
|
-
print " Creating nginx config for app,"
|
|
22
|
-
provision_server.run! "bard setup"
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
puts " ✓"
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def http_responding?
|
|
29
|
-
system "nc -zv #{provision_server.ssh_uri.host} 80 2>/dev/null"
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def app_configured?
|
|
33
|
-
provision_server.run "[ -f /etc/nginx/sites-enabled/#{server.project_name} ]", quiet: true
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
|
data/lib/bard/provision/repo.rb
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
require "bard/github"
|
|
2
|
-
|
|
3
|
-
# generate and install ssh public key into deploy keys
|
|
4
|
-
# add repo to known hosts
|
|
5
|
-
# clone repo
|
|
6
|
-
|
|
7
|
-
class Bard::Provision::Repo < Bard::Provision
|
|
8
|
-
def call
|
|
9
|
-
print "Repo:"
|
|
10
|
-
if !already_cloned?
|
|
11
|
-
if !can_clone_project?
|
|
12
|
-
if !ssh_keypair?
|
|
13
|
-
print " Generating keypair in ~/.ssh,"
|
|
14
|
-
provision_server.run! "ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -q -N \"\"", home: true
|
|
15
|
-
end
|
|
16
|
-
print " Add public key to GitHub repo deploy keys,"
|
|
17
|
-
title = "#{server.ssh_uri.user}@#{server.ssh_uri.host}"
|
|
18
|
-
key = provision_server.run "cat ~/.ssh/id_rsa.pub", home: true
|
|
19
|
-
Bard::Github.new(server.project_name).add_deploy_key title:, key:
|
|
20
|
-
end
|
|
21
|
-
print " Cloning repo,"
|
|
22
|
-
provision_server.run! "git clone git@github.com:botandrosedesign/#{project_name}", home: true
|
|
23
|
-
else
|
|
24
|
-
if !on_latest_master?
|
|
25
|
-
print " Updating to latest master,"
|
|
26
|
-
update_to_latest_master!
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
puts " ✓"
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
private
|
|
34
|
-
|
|
35
|
-
def ssh_keypair?
|
|
36
|
-
provision_server.run "[ -f ~/.ssh/id_rsa.pub ]", home: true, quiet: true
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def already_cloned?
|
|
40
|
-
provision_server.run "[ -d ~/#{project_name}/.git ]", home: true, quiet: true
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def can_clone_project?
|
|
44
|
-
github_url = "git@github.com:botandrosedesign/#{project_name}"
|
|
45
|
-
provision_server.run [
|
|
46
|
-
"needle=$(ssh-keyscan -t ed25519 github.com 2>/dev/null | cut -d \" \" -f 2-3)",
|
|
47
|
-
"grep -q \"$needle\" ~/.ssh/known_hosts || ssh-keyscan -H github.com >> ~/.ssh/known_hosts 2>/dev/null",
|
|
48
|
-
"git ls-remote #{github_url}",
|
|
49
|
-
].join("; "), home: true, quiet: true
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def project_name
|
|
53
|
-
server.project_name
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def on_latest_master?
|
|
57
|
-
provision_server.run [
|
|
58
|
-
"cd ~/#{project_name}",
|
|
59
|
-
"git fetch origin",
|
|
60
|
-
"[ $(git rev-parse HEAD) = $(git rev-parse origin/master) ]"
|
|
61
|
-
].join(" && "), home: true, quiet: true
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def update_to_latest_master!
|
|
65
|
-
provision_server.run! [
|
|
66
|
-
"cd ~/#{project_name}",
|
|
67
|
-
"git checkout master",
|
|
68
|
-
"git reset --hard origin/master"
|
|
69
|
-
].join(" && "), home: true
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
data/lib/bard/provision/rvm.rb
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# install rvm if missing
|
|
2
|
-
|
|
3
|
-
class Bard::Provision::RVM < Bard::Provision
|
|
4
|
-
def call
|
|
5
|
-
print "RVM:"
|
|
6
|
-
if !provision_server.run "[ -d ~/.rvm ]", quiet: true
|
|
7
|
-
print " Installing RVM,"
|
|
8
|
-
provision_server.run! [
|
|
9
|
-
%(sed -i "1i[[ -s \\"$HOME/.rvm/scripts/rvm\\" ]] && source \\"$HOME/.rvm/scripts/rvm\\" # Load RVM into a shell session *as a function*" ~/.bashrc),
|
|
10
|
-
"gpg --keyserver keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB",
|
|
11
|
-
"curl -sSL https://get.rvm.io | bash -s stable",
|
|
12
|
-
].join("; ")
|
|
13
|
-
version = File.read(".ruby-version").chomp
|
|
14
|
-
print " Installing Ruby #{version},"
|
|
15
|
-
provision_server.run! "rvm install #{version}"
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
puts " ✓"
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
|
data/lib/bard/provision/ssh.rb
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# move ssh port
|
|
2
|
-
# add to known hosts
|
|
3
|
-
|
|
4
|
-
class Bard::Provision::SSH < Bard::Provision
|
|
5
|
-
def call
|
|
6
|
-
print "SSH:"
|
|
7
|
-
|
|
8
|
-
if password_auth_enabled?
|
|
9
|
-
print " Disabling password authentication,"
|
|
10
|
-
disable_password_auth!
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
if !ssh_available?(provision_server.ssh_uri, port: target_port)
|
|
14
|
-
if !ssh_available?(provision_server.ssh_uri)
|
|
15
|
-
raise "can't find SSH on port #{target_port} or #{provision_server.ssh_uri.port || 22}"
|
|
16
|
-
end
|
|
17
|
-
if !ssh_known_host?(provision_server.ssh_uri)
|
|
18
|
-
print " Adding known host,"
|
|
19
|
-
add_ssh_known_host!(provision_server.ssh_uri)
|
|
20
|
-
end
|
|
21
|
-
print " Reconfiguring port to #{target_port},"
|
|
22
|
-
provision_server.run! %(echo "Port #{target_port}" | sudo tee /etc/ssh/sshd_config.d/port_#{target_port}.conf; sudo service ssh restart), home: true
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
if !ssh_known_host?(provision_server.ssh_uri)
|
|
26
|
-
print " Adding known host,"
|
|
27
|
-
add_ssh_known_host!(provision_server.ssh_uri)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# provision with new target port from now on
|
|
31
|
-
ssh_url.gsub!(/:\d+$/, "")
|
|
32
|
-
ssh_url << ":#{target_port}"
|
|
33
|
-
puts " ✓"
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
private
|
|
37
|
-
|
|
38
|
-
def target_port
|
|
39
|
-
server.ssh_uri.port || 22
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def ssh_available? ssh_uri, port: nil
|
|
43
|
-
port ||= ssh_uri.port || 22
|
|
44
|
-
system "nc -zv #{ssh_uri.host} #{port} 2>/dev/null"
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def ssh_known_host? ssh_uri
|
|
48
|
-
port ||= ssh_uri.port || 22
|
|
49
|
-
system "grep -q \"$(ssh-keyscan -t ed25519 -p#{port} #{ssh_uri.host} 2>/dev/null | cut -d ' ' -f 2-3)\" ~/.ssh/known_hosts"
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def add_ssh_known_host! ssh_uri
|
|
53
|
-
port ||= ssh_uri.port || 22
|
|
54
|
-
system "ssh-keyscan -p#{port} -H #{ssh_uri.host} >> ~/.ssh/known_hosts 2>/dev/null"
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def password_auth_enabled?
|
|
58
|
-
result = provision_server.run!(
|
|
59
|
-
%q{grep -E '^\s*PasswordAuthentication\s+yes' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf 2>/dev/null || true},
|
|
60
|
-
home: true,
|
|
61
|
-
capture: true
|
|
62
|
-
)
|
|
63
|
-
!!(result && !result.strip.empty?)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def disable_password_auth!
|
|
67
|
-
provision_server.run!(
|
|
68
|
-
%q{echo "PasswordAuthentication no" | sudo tee /etc/ssh/sshd_config.d/disable_password_auth.conf; sudo service ssh restart},
|
|
69
|
-
home: true
|
|
70
|
-
)
|
|
71
|
-
end
|
|
72
|
-
end
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# setup swapfile
|
|
2
|
-
|
|
3
|
-
class Bard::Provision::Swapfile < Bard::Provision
|
|
4
|
-
def call
|
|
5
|
-
print "Swapfile:"
|
|
6
|
-
|
|
7
|
-
provision_server.run! <<~SH
|
|
8
|
-
if [ ! -f /swapfile ]; then
|
|
9
|
-
sudo fallocate -l $(grep MemTotal /proc/meminfo | awk '{print $2}')K /swapfile
|
|
10
|
-
fi
|
|
11
|
-
sudo chmod 600 /swapfile
|
|
12
|
-
sudo swapon --show | grep -q '/swapfile' || sudo mkswap /swapfile
|
|
13
|
-
sudo swapon --show | grep -q '/swapfile' || sudo swapon /swapfile
|
|
14
|
-
grep -q '/swapfile none swap sw 0 0' /etc/fstab || echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
|
|
15
|
-
SH
|
|
16
|
-
|
|
17
|
-
puts " ✓"
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
|
data/lib/bard/provision/user.rb
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
# rename user
|
|
2
|
-
|
|
3
|
-
class Bard::Provision::User < Bard::Provision
|
|
4
|
-
def call
|
|
5
|
-
print "User:"
|
|
6
|
-
|
|
7
|
-
if !ssh_with_user?(provision_server.ssh_uri, user: new_user)
|
|
8
|
-
if !ssh_with_user?(provision_server.ssh_uri)
|
|
9
|
-
raise "can't ssh in with user #{new_user} or #{old_user}"
|
|
10
|
-
end
|
|
11
|
-
print " Adding user #{new_user},"
|
|
12
|
-
provision_server.run! [
|
|
13
|
-
"sudo useradd -m -s /bin/bash #{new_user}",
|
|
14
|
-
"sudo usermod -aG sudo #{new_user}",
|
|
15
|
-
"echo \"#{new_user} ALL=(ALL) NOPASSWD:ALL\" | sudo tee -a /etc/sudoers",
|
|
16
|
-
"sudo mkdir -p ~#{new_user}/.ssh",
|
|
17
|
-
"sudo cp ~/.ssh/authorized_keys ~#{new_user}/.ssh/authorized_keys",
|
|
18
|
-
"sudo chown -R #{new_user}:#{new_user} ~#{new_user}/.ssh",
|
|
19
|
-
"sudo chmod +rx ~#{new_user}", # so nginx and passenger can read it
|
|
20
|
-
].join("; "), home: true
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# provision with new user from now on
|
|
24
|
-
ssh_url.gsub!("#{old_user}@", "#{new_user}@")
|
|
25
|
-
puts " ✓"
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
private
|
|
29
|
-
|
|
30
|
-
def new_user
|
|
31
|
-
server.ssh_uri.user
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def old_user
|
|
35
|
-
provision_server.ssh_uri.user
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def ssh_with_user? ssh_uri, user: ssh_uri.user
|
|
39
|
-
system "ssh -o ConnectTimeout=2 -p#{ssh_uri.port || 22} #{user}@#{ssh_uri.host} : >/dev/null 2>&1"
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
data/lib/bard/provision.rb
DELETED
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
|