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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +2 -2
- data/CLAUDE.md +1 -1
- data/PLUGINS.md +31 -46
- data/bard.gemspec +2 -1
- data/features/ci.feature +1 -0
- data/features/data.feature +1 -0
- data/features/deploy.feature +1 -0
- data/features/deploy_git_workflow.feature +1 -0
- data/features/run.feature +1 -0
- data/features/step_definitions/bard_steps.rb +1 -0
- data/features/support/test_server.rb +3 -3
- data/lib/bard/cli.rb +9 -28
- data/lib/bard/command.rb +9 -88
- data/lib/bard/config.rb +38 -177
- data/lib/bard/copy.rb +28 -82
- data/lib/bard/plugins/data.rb +56 -0
- data/lib/bard/{ci → plugins/deploy/ci}/github_actions.rb +2 -2
- data/lib/bard/{ci → plugins/deploy/ci}/jenkins.rb +1 -1
- data/lib/bard/{ci → plugins/deploy/ci}/local.rb +1 -1
- data/lib/bard/{ci → plugins/deploy/ci}/runner.rb +3 -3
- data/lib/bard/{ci.rb → plugins/deploy/ci.rb} +1 -1
- data/lib/bard/plugins/deploy/ssh_strategy.rb +27 -0
- data/lib/bard/{deploy_strategy.rb → plugins/deploy/strategy.rb} +1 -4
- 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} +2 -2
- data/lib/bard/{deploy_strategy/github_pages.rb → plugins/github_pages/strategy.rb} +3 -4
- data/lib/bard/plugins/github_pages.rb +11 -15
- data/lib/bard/plugins/hurt.rb +12 -4
- 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 +7 -3
- 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 +8 -4
- 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} +10 -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 +5 -4
- data/lib/bard/retryable.rb +25 -0
- data/lib/bard/target.rb +21 -230
- data/lib/bard/version.rb +1 -1
- data/lib/bard.rb +1 -3
- data/spec/acceptance/docker/Dockerfile +1 -1
- data/spec/bard/capability_spec.rb +8 -50
- data/spec/bard/ci/github_actions_spec.rb +1 -1
- data/spec/bard/ci/jenkins_spec.rb +1 -1
- data/spec/bard/ci/runner_spec.rb +3 -3
- data/spec/bard/ci_spec.rb +1 -1
- data/spec/bard/cli/ci_spec.rb +4 -23
- data/spec/bard/cli/data_spec.rb +7 -26
- data/spec/bard/cli/deploy_spec.rb +43 -40
- data/spec/bard/cli/hurt_spec.rb +2 -8
- data/spec/bard/cli/install_spec.rb +4 -10
- data/spec/bard/cli/master_key_spec.rb +5 -19
- data/spec/bard/cli/open_spec.rb +17 -35
- data/spec/bard/cli/ping_spec.rb +10 -25
- data/spec/bard/cli/run_spec.rb +10 -23
- 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 +17 -32
- data/spec/bard/cli/vim_spec.rb +5 -11
- data/spec/bard/command_spec.rb +1 -10
- data/spec/bard/config_spec.rb +68 -116
- 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 +1 -1
- data/spec/bard/ping_spec.rb +5 -5
- data/spec/bard/ssh_copy_spec.rb +44 -0
- data/spec/bard/ssh_server_spec.rb +1 -98
- data/spec/bard/target_spec.rb +61 -108
- metadata +50 -124
- data/lib/bard/ci/retryable.rb +0 -27
- data/lib/bard/cli/ci.rb +0 -73
- data/lib/bard/cli/command.rb +0 -26
- data/lib/bard/cli/data.rb +0 -45
- data/lib/bard/cli/deploy.rb +0 -116
- data/lib/bard/cli/hurt.rb +0 -15
- data/lib/bard/cli/install.rb +0 -11
- 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 -18
- data/lib/bard/cli/ping.rb +0 -12
- data/lib/bard/cli/provision.rb +0 -34
- data/lib/bard/cli/run.rb +0 -26
- data/lib/bard/cli/setup.rb +0 -56
- data/lib/bard/cli/ssh.rb +0 -14
- data/lib/bard/cli/stage.rb +0 -35
- data/lib/bard/cli/vim.rb +0 -8
- data/lib/bard/default_config.rb +0 -35
- data/lib/bard/deploy_strategy/ssh.rb +0 -19
- data/lib/bard/deprecation.rb +0 -19
- data/lib/bard/github_pages.rb +0 -134
- data/lib/bard/plugin.rb +0 -100
- data/lib/bard/plugins/backup.rb +0 -19
- data/lib/bard/plugins/jenkins.rb +0 -6
- data/lib/bard/plugins/new.rb +0 -5
- data/lib/bard/plugins/provision.rb +0 -5
- 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 -79
- data/lib/bard/provision/swapfile.rb +0 -23
- data/lib/bard/provision/user.rb +0 -42
- data/lib/bard/provision.rb +0 -16
- data/lib/bard/server.rb +0 -160
- 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/deprecation_spec.rb +0 -281
- data/spec/bard/github_pages_spec.rb +0 -143
- data/spec/bard/plugin_spec.rb +0 -79
- 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 -242
- data/spec/bard/provision/swapfile_spec.rb +0 -33
- 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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 24a9ee78c591a6446ac1bb749225497c75470e12e4fe822d96e975870ac88152
|
|
4
|
+
data.tar.gz: 2b8ae0acbf1237b3312957128130f399a516a3a19d52d45f63c7b0677952e4f2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 55a1a4f6fcf3bf12201105974a619be5178c3c9c6367d8dccf2eef1e7e504880a869a6291dfb5024930e025f63d8cf2f22c8925cf5fc24f9e83d2aa85ed047ed
|
|
7
|
+
data.tar.gz: 5da5d707ceed5ca663e4a68cd4a2ba2afbb232052e4a0542a4e41a1badc0161ba4eda410195b717d21f8fdaea299af771afa6a19310d93b66915996e8579b5fa
|
data/.github/workflows/ci.yml
CHANGED
|
@@ -5,7 +5,7 @@ jobs:
|
|
|
5
5
|
strategy:
|
|
6
6
|
fail-fast: false
|
|
7
7
|
matrix:
|
|
8
|
-
ruby: [ "3.
|
|
8
|
+
ruby: [ "3.3", "3.4", "4.0" ]
|
|
9
9
|
|
|
10
10
|
runs-on: ubuntu-latest
|
|
11
11
|
steps:
|
|
@@ -36,7 +36,7 @@ jobs:
|
|
|
36
36
|
|
|
37
37
|
- name: Build test container image
|
|
38
38
|
run: |
|
|
39
|
-
sudo podman pull ubuntu:
|
|
39
|
+
sudo podman pull ubuntu:24.04
|
|
40
40
|
sudo podman build -t bard-test-server -f spec/acceptance/docker/Dockerfile spec/acceptance/docker
|
|
41
41
|
|
|
42
42
|
- name: Run tests
|
data/CLAUDE.md
CHANGED
|
@@ -44,7 +44,7 @@ bundle exec bin/bard
|
|
|
44
44
|
- **`Bard::CLI`** (`lib/bard/cli.rb`) - Thor-based command dispatcher. Commands are modules in `lib/bard/cli/` included into CLI.
|
|
45
45
|
- **`Bard::Config`** (`lib/bard/config.rb`) - DSL parser for `bard.rb` files. Manages targets and settings.
|
|
46
46
|
- **`Bard::Target`** (`lib/bard/target.rb`) - Deployment destination with capabilities (ssh, ping, data). Supports dynamic strategy DSL via `method_missing`.
|
|
47
|
-
- **`Bard::
|
|
47
|
+
- **`Bard::SSHServer`** (`lib/bard/ssh_server.rb`) - SSH connection details (user, host, port, gateway, ssh_key, env).
|
|
48
48
|
- **`Bard::DeployStrategy`** (`lib/bard/deploy_strategy.rb`) - Base class for deployment strategies. Subclasses auto-register via Ruby's `inherited` hook.
|
|
49
49
|
|
|
50
50
|
### Capability System
|
data/PLUGINS.md
CHANGED
|
@@ -4,18 +4,37 @@ Bard uses a plugin system to extend functionality. Plugins can add CLI commands,
|
|
|
4
4
|
|
|
5
5
|
## Plugin Structure
|
|
6
6
|
|
|
7
|
-
Plugins live in `lib/bard/plugins/` and register
|
|
7
|
+
Plugins live in `lib/bard/plugins/` and are auto-loaded. Command classes auto-register when they subclass `Bard::Plugin::Command`:
|
|
8
8
|
|
|
9
9
|
```ruby
|
|
10
10
|
# lib/bard/plugins/my_plugin.rb
|
|
11
11
|
require "bard/plugin"
|
|
12
12
|
|
|
13
|
-
Bard::
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
class Bard::CLI::MyPlugin < Bard::Plugin::Command
|
|
14
|
+
desc "mycommand", "Description of my command"
|
|
15
|
+
option :verbose, type: :boolean
|
|
16
|
+
def mycommand
|
|
17
|
+
puts "Hello from my plugin!"
|
|
18
|
+
puts config[:production].url
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
That's it — no registration block needed. The `Command` base class provides:
|
|
24
|
+
- Automatic registration via Ruby's `inherited` hook
|
|
25
|
+
- `desc` and `option` class methods for Thor integration
|
|
26
|
+
- Delegation to the CLI instance (access to `config`, `project_name`, `run!`, `options`, etc.)
|
|
27
|
+
|
|
28
|
+
## Extending Target and Config
|
|
16
29
|
|
|
17
|
-
|
|
18
|
-
|
|
30
|
+
To add methods to `Bard::Target` or `Bard::Config`, reopen the class directly:
|
|
31
|
+
|
|
32
|
+
```ruby
|
|
33
|
+
# lib/bard/plugins/my_plugin.rb
|
|
34
|
+
require "bard/target"
|
|
35
|
+
|
|
36
|
+
class Bard::Target
|
|
37
|
+
def my_feature(url = nil)
|
|
19
38
|
if url.nil?
|
|
20
39
|
@my_feature_url
|
|
21
40
|
else
|
|
@@ -23,9 +42,12 @@ Bard::Plugin.register :my_plugin do
|
|
|
23
42
|
enable_capability(:my_feature)
|
|
24
43
|
end
|
|
25
44
|
end
|
|
45
|
+
end
|
|
26
46
|
|
|
27
|
-
|
|
28
|
-
|
|
47
|
+
require "bard/config"
|
|
48
|
+
|
|
49
|
+
class Bard::Config
|
|
50
|
+
def my_global_setting(value = nil)
|
|
29
51
|
if value.nil?
|
|
30
52
|
@my_global_setting
|
|
31
53
|
else
|
|
@@ -35,43 +57,6 @@ Bard::Plugin.register :my_plugin do
|
|
|
35
57
|
end
|
|
36
58
|
```
|
|
37
59
|
|
|
38
|
-
## CLI Commands
|
|
39
|
-
|
|
40
|
-
CLI commands inherit from `Bard::CLI::Command` and implement a `setup` class method:
|
|
41
|
-
|
|
42
|
-
```ruby
|
|
43
|
-
# lib/bard/cli/my_plugin.rb
|
|
44
|
-
require "bard/cli/command"
|
|
45
|
-
|
|
46
|
-
class Bard::CLI::MyPlugin < Bard::CLI::Command
|
|
47
|
-
desc "mycommand", "Description of my command"
|
|
48
|
-
def mycommand
|
|
49
|
-
puts "Hello from my plugin!"
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
The `Command` base class provides:
|
|
55
|
-
- Automatic `setup` that registers the command with the CLI
|
|
56
|
-
- Delegation to the CLI instance (access to `config`, `project_name`, etc.)
|
|
57
|
-
- `desc` and `option` class methods for Thor integration
|
|
58
|
-
|
|
59
|
-
For Thor subcommand groups (nested under `bard mygroup`):
|
|
60
|
-
|
|
61
|
-
```ruby
|
|
62
|
-
# lib/bard/cli/my_subcommand.rb
|
|
63
|
-
class Bard::CLI::MySubcommand < Thor
|
|
64
|
-
def self.setup(cli)
|
|
65
|
-
cli.register(self, "mygroup", "mygroup COMMAND", "My subcommand group")
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
desc "action", "Do something"
|
|
69
|
-
def action
|
|
70
|
-
puts "Hello from subcommand!"
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
```
|
|
74
|
-
|
|
75
60
|
## Adding Strategies
|
|
76
61
|
|
|
77
62
|
Plugins can add deployment strategies or CI runners:
|
|
@@ -111,4 +96,4 @@ Strategies auto-register via Ruby's `inherited` hook. The class name determines
|
|
|
111
96
|
|
|
112
97
|
## Plugin Loading
|
|
113
98
|
|
|
114
|
-
Plugins are loaded automatically from `lib/bard/plugins/`. The load order is alphabetical by filename.
|
|
99
|
+
Plugins are loaded automatically from `lib/bard/plugins/`. The load order is alphabetical by filename. External plugins are loaded from the project's `lib/bard/plugins/` directory.
|
data/bard.gemspec
CHANGED
|
@@ -15,11 +15,11 @@ Gem::Specification.new do |spec|
|
|
|
15
15
|
spec.files = `git ls-files -z`.split("\x0")
|
|
16
16
|
spec.executables = ["bard"]
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
18
|
+
spec.required_ruby_version = ">= 3.3"
|
|
18
19
|
spec.require_paths = ["lib"]
|
|
19
20
|
|
|
20
21
|
spec.add_dependency "thor", ">= 0.19.0"
|
|
21
22
|
spec.add_dependency "rvm"
|
|
22
|
-
spec.add_dependency "term-ansicolor", ">= 1.0.3"
|
|
23
23
|
spec.add_dependency "rbnacl"
|
|
24
24
|
spec.add_dependency "base64"
|
|
25
25
|
|
|
@@ -28,4 +28,5 @@ Gem::Specification.new do |spec|
|
|
|
28
28
|
spec.add_development_dependency "debug"
|
|
29
29
|
spec.add_development_dependency "cucumber"
|
|
30
30
|
spec.add_development_dependency "testcontainers"
|
|
31
|
+
spec.add_development_dependency "ostruct"
|
|
31
32
|
end
|
data/features/ci.feature
CHANGED
data/features/data.feature
CHANGED
data/features/deploy.feature
CHANGED
data/features/run.feature
CHANGED
|
@@ -53,7 +53,7 @@ module TestServerWorld
|
|
|
53
53
|
return
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
system("podman pull ubuntu:
|
|
56
|
+
system("podman pull ubuntu:24.04 >/dev/null 2>&1")
|
|
57
57
|
|
|
58
58
|
docker_dir = File.join(ROOT, "spec/acceptance/docker")
|
|
59
59
|
unless system("podman build -t bard-test-server -f #{docker_dir}/Dockerfile #{docker_dir} 2>&1")
|
|
@@ -207,10 +207,10 @@ end
|
|
|
207
207
|
|
|
208
208
|
World(TestServerWorld)
|
|
209
209
|
|
|
210
|
-
Before do
|
|
210
|
+
Before("@server") do
|
|
211
211
|
start_test_server
|
|
212
212
|
end
|
|
213
213
|
|
|
214
|
-
After do
|
|
214
|
+
After("@server") do
|
|
215
215
|
stop_test_server
|
|
216
216
|
end
|
data/lib/bard/cli.rb
CHANGED
|
@@ -4,36 +4,11 @@ require "thor"
|
|
|
4
4
|
require "bard/version"
|
|
5
5
|
require "bard/config"
|
|
6
6
|
require "bard/command"
|
|
7
|
-
require "bard/plugin"
|
|
8
|
-
require "term/ansicolor"
|
|
9
7
|
|
|
10
8
|
module Bard
|
|
11
9
|
class CLI < Thor
|
|
12
|
-
include Term::ANSIColor
|
|
13
|
-
|
|
14
10
|
class_option :verbose, type: :boolean, aliases: :v
|
|
15
11
|
|
|
16
|
-
{
|
|
17
|
-
data: "Data",
|
|
18
|
-
stage: "Stage",
|
|
19
|
-
deploy: "Deploy",
|
|
20
|
-
ci: "CI",
|
|
21
|
-
master_key: "MasterKey",
|
|
22
|
-
setup: "Setup",
|
|
23
|
-
run: "Run",
|
|
24
|
-
ssh: "SSH",
|
|
25
|
-
}.each do |command, klass|
|
|
26
|
-
require "bard/cli/#{command}"
|
|
27
|
-
include const_get(klass)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
Plugin.load_all!
|
|
31
|
-
Plugin.all.each { |plugin| plugin.apply_to_cli(self) }
|
|
32
|
-
|
|
33
|
-
# Load core CI runners AFTER plugins so GithubActions is the default (last registered wins)
|
|
34
|
-
require "bard/ci/local"
|
|
35
|
-
require "bard/ci/github_actions"
|
|
36
|
-
|
|
37
12
|
map "--version" => :version
|
|
38
13
|
desc "version", "Display version"
|
|
39
14
|
def version
|
|
@@ -43,6 +18,10 @@ module Bard
|
|
|
43
18
|
def self.exit_on_failure? = true
|
|
44
19
|
|
|
45
20
|
no_commands do
|
|
21
|
+
def red(text) = "\e[31m#{text}\e[0m"
|
|
22
|
+
def yellow(text) = "\e[33m#{text}\e[0m"
|
|
23
|
+
def green(text) = "\e[32m#{text}\e[0m"
|
|
24
|
+
|
|
46
25
|
def run!(...)
|
|
47
26
|
Bard::Command.run!(...)
|
|
48
27
|
rescue Bard::Command::Error => e
|
|
@@ -51,13 +30,15 @@ module Bard
|
|
|
51
30
|
end
|
|
52
31
|
|
|
53
32
|
def config
|
|
54
|
-
@config ||= Bard::Config.
|
|
33
|
+
@config ||= Bard::Config.current
|
|
55
34
|
end
|
|
56
35
|
|
|
57
36
|
def project_name
|
|
58
|
-
|
|
37
|
+
config.project_name
|
|
59
38
|
end
|
|
60
39
|
end
|
|
40
|
+
|
|
41
|
+
# load plugins from bard and other gems
|
|
42
|
+
Gem.find_files("bard/plugins/*.rb").sort.each { |path| require path }
|
|
61
43
|
end
|
|
62
44
|
end
|
|
63
|
-
|
data/lib/bard/command.rb
CHANGED
|
@@ -1,43 +1,20 @@
|
|
|
1
1
|
require "open3"
|
|
2
|
-
require "shellwords"
|
|
3
2
|
|
|
4
3
|
module Bard
|
|
5
|
-
|
|
4
|
+
module Command
|
|
6
5
|
class Error < RuntimeError; end
|
|
7
6
|
|
|
8
|
-
def self.run!
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def self.run command, on: :local, home: false, verbose: false, quiet: false
|
|
13
|
-
new(command, on, home).run verbose:, quiet:
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def self.exec! command, on: :local, home: false
|
|
17
|
-
new(command, on, home).exec!
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def run! verbose: false, quiet: false
|
|
21
|
-
result = run(verbose:, quiet:)
|
|
22
|
-
raise Error.new(full_command) unless result
|
|
7
|
+
def self.run!(command, verbose: false, quiet: false)
|
|
8
|
+
result = run(command, verbose:, quiet:)
|
|
9
|
+
raise Error.new(command) unless result
|
|
23
10
|
result
|
|
24
11
|
end
|
|
25
12
|
|
|
26
|
-
def run verbose: false, quiet: false
|
|
27
|
-
# no-op if server doesn't really exist
|
|
28
|
-
if on.to_sym != :local
|
|
29
|
-
# Check for new Target architecture
|
|
30
|
-
if on.respond_to?(:server) && on.server.nil?
|
|
31
|
-
return true
|
|
32
|
-
# Check for old Server architecture
|
|
33
|
-
elsif on.respond_to?(:ssh) && on.ssh == false
|
|
34
|
-
return true
|
|
35
|
-
end
|
|
36
|
-
end
|
|
13
|
+
def self.run(command, verbose: false, quiet: false)
|
|
37
14
|
if verbose
|
|
38
|
-
system
|
|
15
|
+
system command
|
|
39
16
|
else
|
|
40
|
-
stdout, stderr, status = Open3.capture3(
|
|
17
|
+
stdout, stderr, status = Open3.capture3(command)
|
|
41
18
|
failed = status.to_i.nonzero?
|
|
42
19
|
if failed && !quiet
|
|
43
20
|
$stdout.puts stdout
|
|
@@ -47,64 +24,8 @@ module Bard
|
|
|
47
24
|
end
|
|
48
25
|
end
|
|
49
26
|
|
|
50
|
-
def exec!
|
|
51
|
-
exec
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
private
|
|
55
|
-
|
|
56
|
-
def full_command quiet: false
|
|
57
|
-
if on.to_sym == :local
|
|
58
|
-
command
|
|
59
|
-
else
|
|
60
|
-
remote_command quiet: false
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def remote_command quiet: false
|
|
65
|
-
# Support both new Target (with server attribute) and old Server architecture
|
|
66
|
-
ssh_server = on.respond_to?(:server) ? on.server : on
|
|
67
|
-
|
|
68
|
-
# Get options from Target first (for deprecated separate method calls), fall back to SSHServer
|
|
69
|
-
env_value = on.respond_to?(:env) ? on.env : nil
|
|
70
|
-
env_value ||= ssh_server.env if ssh_server.respond_to?(:env)
|
|
71
|
-
|
|
72
|
-
ssh_key = on.respond_to?(:ssh_key) ? on.ssh_key : nil
|
|
73
|
-
ssh_key ||= ssh_server.ssh_key if ssh_server.respond_to?(:ssh_key)
|
|
74
|
-
|
|
75
|
-
gateway = on.respond_to?(:gateway) ? on.gateway : nil
|
|
76
|
-
gateway ||= ssh_server.gateway if ssh_server.respond_to?(:gateway)
|
|
77
|
-
|
|
78
|
-
cmd = command
|
|
79
|
-
cmd = "#{env_value} #{command}" if env_value
|
|
80
|
-
|
|
81
|
-
unless home
|
|
82
|
-
path = on.respond_to?(:path) ? on.path : ssh_server.path
|
|
83
|
-
cmd = "cd #{path} && #{cmd}" if path
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
ssh_opts = ["-tt", "-o StrictHostKeyChecking=no", "-o UserKnownHostsFile=/dev/null", "-o LogLevel=ERROR"]
|
|
87
|
-
ssh_opts << "-i #{ssh_key}" if ssh_key
|
|
88
|
-
|
|
89
|
-
# Handle new SSHServer vs old Server architecture
|
|
90
|
-
if ssh_server.respond_to?(:host)
|
|
91
|
-
# New SSHServer - has separate host/port/user
|
|
92
|
-
ssh_opts << "-p #{ssh_server.port}" if ssh_server.port && ssh_server.port != "22"
|
|
93
|
-
ssh_opts << "-o ProxyJump=#{gateway}" if gateway
|
|
94
|
-
ssh_target = "#{ssh_server.user}@#{ssh_server.host}"
|
|
95
|
-
else
|
|
96
|
-
# Old Server - uses URI-based ssh_uri
|
|
97
|
-
ssh_target = ssh_server.ssh_uri
|
|
98
|
-
if gateway
|
|
99
|
-
gateway_uri = ssh_server.ssh_uri(:gateway)
|
|
100
|
-
ssh_opts << "-o ProxyJump=#{gateway_uri}"
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
cmd = "ssh #{ssh_opts.join(' ')} #{ssh_target} #{Shellwords.shellescape(cmd)}"
|
|
105
|
-
|
|
106
|
-
cmd += " 2>&1" if quiet
|
|
107
|
-
cmd
|
|
27
|
+
def self.exec!(command)
|
|
28
|
+
Kernel.exec command
|
|
108
29
|
end
|
|
109
30
|
end
|
|
110
31
|
end
|
data/lib/bard/config.rb
CHANGED
|
@@ -1,218 +1,79 @@
|
|
|
1
|
-
require "bard/server"
|
|
2
1
|
require "bard/target"
|
|
3
|
-
require "bard/
|
|
2
|
+
require "bard/plugins/ssh/target_methods"
|
|
3
|
+
require "bard/plugins/ping/target_methods"
|
|
4
4
|
|
|
5
5
|
module Bard
|
|
6
6
|
class Config
|
|
7
|
-
def self.current
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
def self.current
|
|
8
|
+
new(detect_project_name, path: "bard.rb")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.detect_project_name
|
|
12
|
+
git_common_dir = `git rev-parse --git-common-dir 2>/dev/null`.chomp
|
|
13
|
+
dirname = if $?.success? && !git_common_dir.empty?
|
|
14
|
+
File.dirname(File.expand_path(git_common_dir))
|
|
15
|
+
else
|
|
16
|
+
Dir.getwd
|
|
17
|
+
end
|
|
18
|
+
File.basename(dirname)
|
|
11
19
|
end
|
|
12
20
|
|
|
13
21
|
attr_reader :project_name, :targets
|
|
14
22
|
|
|
15
23
|
def initialize(project_name = nil, path: nil, source: nil)
|
|
16
|
-
# Support both positional and keyword argument for project_name
|
|
17
24
|
@project_name = project_name
|
|
18
|
-
@
|
|
19
|
-
@data_paths = []
|
|
20
|
-
@backup = nil
|
|
21
|
-
@ci_system = nil
|
|
22
|
-
|
|
23
|
-
# Load default configuration (creates Server instances for backward compat)
|
|
25
|
+
@targets = {}
|
|
24
26
|
load_defaults if project_name
|
|
25
27
|
|
|
26
|
-
# Load user configuration
|
|
27
28
|
if path && File.exist?(path)
|
|
28
29
|
source = File.read(path)
|
|
29
30
|
end
|
|
30
31
|
if source
|
|
31
|
-
instance_eval(source)
|
|
32
|
+
instance_eval(source, path)
|
|
32
33
|
end
|
|
33
34
|
end
|
|
34
35
|
|
|
35
|
-
# Backward compatible accessor
|
|
36
|
-
def servers
|
|
37
|
-
@servers
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# New v2.0 accessor (same as servers)
|
|
41
|
-
def targets
|
|
42
|
-
@servers
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Old v1.x API - creates Server instances
|
|
46
|
-
def server(key, &block)
|
|
47
|
-
Deprecation.warn "`server` is deprecated; use `target` instead (will be removed in v2.0)"
|
|
48
|
-
key = key.to_sym
|
|
49
|
-
@servers[key] = Server.define(project_name, key, &block)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
36
|
def remove_target(key)
|
|
53
|
-
@
|
|
37
|
+
@targets.delete(key.to_sym)
|
|
54
38
|
end
|
|
55
39
|
|
|
56
|
-
# New v2.0 API - creates Target instances
|
|
57
40
|
def target(key, &block)
|
|
58
41
|
key = key.to_sym
|
|
59
|
-
unless @
|
|
60
|
-
@
|
|
42
|
+
unless @targets[key].is_a?(Target)
|
|
43
|
+
@targets[key] = Target.new(key, self)
|
|
61
44
|
end
|
|
62
|
-
@
|
|
63
|
-
@
|
|
45
|
+
@targets[key].instance_eval(&block) if block
|
|
46
|
+
@targets[key]
|
|
64
47
|
end
|
|
65
48
|
|
|
66
|
-
# Get a server/target by key
|
|
67
49
|
def [](key)
|
|
68
|
-
key
|
|
69
|
-
# Fallback to staging if production not defined
|
|
70
|
-
if @servers[key].nil? && key == :production
|
|
71
|
-
key = :staging
|
|
72
|
-
end
|
|
73
|
-
@servers[key]
|
|
50
|
+
@targets[key.to_sym]
|
|
74
51
|
end
|
|
75
52
|
|
|
76
|
-
|
|
77
|
-
def data(*paths)
|
|
78
|
-
if paths.empty?
|
|
79
|
-
@data_paths
|
|
80
|
-
else
|
|
81
|
-
@data_paths = paths
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def data_paths
|
|
86
|
-
@data_paths
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def backup(value = nil, &block)
|
|
90
|
-
if block_given?
|
|
91
|
-
@backup = BackupConfig.new(&block)
|
|
92
|
-
elsif value == false
|
|
93
|
-
@backup = BackupConfig.new { disabled }
|
|
94
|
-
elsif value.nil? # Getter
|
|
95
|
-
@backup ||= BackupConfig.new { bard }
|
|
96
|
-
else
|
|
97
|
-
raise ArgumentError, "backup accepts false or a block"
|
|
98
|
-
end
|
|
99
|
-
end
|
|
53
|
+
private
|
|
100
54
|
|
|
101
|
-
def
|
|
102
|
-
|
|
103
|
-
end
|
|
55
|
+
def load_defaults
|
|
56
|
+
target :local
|
|
104
57
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
urls = [hostname]
|
|
110
|
-
if hostname.count(".") < 2
|
|
111
|
-
urls << "www.#{hostname}"
|
|
58
|
+
target :gubs do
|
|
59
|
+
ssh "botandrose@cloud.hackett.world:22022",
|
|
60
|
+
path: "Sites/#{config.project_name}"
|
|
61
|
+
url false
|
|
112
62
|
end
|
|
113
63
|
|
|
114
|
-
target :
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
64
|
+
target :ci do
|
|
65
|
+
ssh "jenkins@staging.botandrose.com:22022",
|
|
66
|
+
path: "jobs/#{config.project_name}/workspace"
|
|
67
|
+
url false
|
|
118
68
|
end
|
|
119
69
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
# CI configuration
|
|
124
|
-
def ci(system = nil)
|
|
125
|
-
if system.nil?
|
|
126
|
-
@ci_system
|
|
127
|
-
else
|
|
128
|
-
@ci_system = system
|
|
70
|
+
staging_defaults = proc do
|
|
71
|
+
ssh "www@staging.botandrose.com:22022"
|
|
72
|
+
url "#{config.project_name}.botandrose.com"
|
|
129
73
|
end
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def ci_system
|
|
133
|
-
@ci_system
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def ci_instance(branch)
|
|
137
|
-
return nil if @ci_system == false
|
|
138
|
-
|
|
139
|
-
require "bard/ci"
|
|
140
|
-
CI.new(project_name, branch, runner_name: @ci_system)
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
private
|
|
144
|
-
|
|
145
|
-
# Load default server configurations (v1.x compatible)
|
|
146
|
-
def load_defaults
|
|
147
|
-
@servers[:local] = Server.new(
|
|
148
|
-
project_name,
|
|
149
|
-
:local,
|
|
150
|
-
false,
|
|
151
|
-
"./",
|
|
152
|
-
["#{project_name}.local"],
|
|
153
|
-
)
|
|
154
|
-
@servers[:gubs] = Server.new(
|
|
155
|
-
project_name,
|
|
156
|
-
:gubs,
|
|
157
|
-
"botandrose@cloud.hackett.world:22022",
|
|
158
|
-
"Sites/#{project_name}",
|
|
159
|
-
false,
|
|
160
|
-
)
|
|
161
|
-
@servers[:ci] = Server.new(
|
|
162
|
-
project_name,
|
|
163
|
-
:ci,
|
|
164
|
-
"jenkins@staging.botandrose.com:22022",
|
|
165
|
-
"jobs/#{project_name}/workspace",
|
|
166
|
-
false,
|
|
167
|
-
)
|
|
168
|
-
@servers[:staging] = Server.new(
|
|
169
|
-
project_name,
|
|
170
|
-
:staging,
|
|
171
|
-
"www@staging.botandrose.com:22022",
|
|
172
|
-
project_name,
|
|
173
|
-
["#{project_name}.botandrose.com"],
|
|
174
|
-
)
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
class BackupConfig
|
|
179
|
-
attr_reader :destinations
|
|
180
|
-
|
|
181
|
-
def initialize(&block)
|
|
182
|
-
@destinations = []
|
|
183
|
-
instance_eval(&block) if block_given?
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
def bard
|
|
187
|
-
@bard = true
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
def bard?
|
|
191
|
-
!!@bard
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
def disabled
|
|
195
|
-
@disabled = true
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
def disabled?
|
|
199
|
-
!!@disabled
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
def enabled?
|
|
203
|
-
!disabled?
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
def s3(name, **kwargs)
|
|
207
|
-
@destinations << {
|
|
208
|
-
name: name,
|
|
209
|
-
type: :s3,
|
|
210
|
-
**kwargs,
|
|
211
|
-
}
|
|
212
|
-
end
|
|
213
74
|
|
|
214
|
-
|
|
215
|
-
|
|
75
|
+
target :staging, &staging_defaults
|
|
76
|
+
target :production, &staging_defaults
|
|
216
77
|
end
|
|
217
78
|
end
|
|
218
79
|
end
|