bard 1.7.4 → 2.0.0.beta
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/ARCHITECTURE.md +957 -0
- data/CUSTOM_STRATEGIES.md +701 -0
- data/MIGRATION_GUIDE.md +498 -0
- data/README.md +489 -0
- data/lib/bard/cli/deploy.rb +12 -3
- data/lib/bard/command.rb +25 -9
- data/lib/bard/config.rb +118 -43
- data/lib/bard/copy.rb +57 -13
- data/lib/bard/default_config.rb +35 -0
- data/lib/bard/deploy_strategy/github_pages.rb +135 -0
- data/lib/bard/deploy_strategy/ssh.rb +19 -0
- data/lib/bard/deploy_strategy.rb +60 -0
- data/lib/bard/ssh_server.rb +100 -0
- data/lib/bard/target.rb +239 -0
- data/lib/bard/version.rb +1 -1
- data/spec/bard/capability_spec.rb +97 -0
- data/spec/bard/config_spec.rb +1 -1
- data/spec/bard/deploy_strategy/ssh_spec.rb +67 -0
- data/spec/bard/deploy_strategy_spec.rb +107 -0
- data/spec/bard/dynamic_dsl_spec.rb +126 -0
- data/spec/bard/ssh_server_spec.rb +169 -0
- data/spec/bard/target_spec.rb +239 -0
- metadata +24 -2
data/README.md
ADDED
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
# Bard
|
|
2
|
+
|
|
3
|
+
A modular deployment tool for Ruby applications that makes deployment simple and extensible.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
# bard.rb
|
|
9
|
+
target :production do
|
|
10
|
+
ssh "deploy@example.com:22"
|
|
11
|
+
end
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
bard deploy production
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- **Modular Capabilities**: Enable only the features you need
|
|
21
|
+
- **Pluggable Strategies**: SSH, GitHub Pages, or create your own
|
|
22
|
+
- **Default Targets**: Pre-configured for common Bot and Rose workflows
|
|
23
|
+
- **Git Integration**: Built-in branch management and safety checks
|
|
24
|
+
- **CI Integration**: Auto-detects GitHub Actions or Jenkins
|
|
25
|
+
- **Data Syncing**: Copy databases and assets between targets
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
Add to your Gemfile:
|
|
30
|
+
|
|
31
|
+
```ruby
|
|
32
|
+
gem 'bard'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or install globally:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
gem install bard
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Core Concepts
|
|
42
|
+
|
|
43
|
+
### Targets
|
|
44
|
+
|
|
45
|
+
A **target** is a deployment destination. Targets can be servers, serverless environments, static hosting, or anything else you can deploy to.
|
|
46
|
+
|
|
47
|
+
```ruby
|
|
48
|
+
target :production do
|
|
49
|
+
ssh "deploy@example.com:22", path: "app"
|
|
50
|
+
end
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Capabilities
|
|
54
|
+
|
|
55
|
+
Capabilities are features enabled on targets. Common capabilities include:
|
|
56
|
+
|
|
57
|
+
- **SSH**: Remote command execution and file transfer
|
|
58
|
+
- **Ping**: Health check URLs
|
|
59
|
+
- **Data**: Database and file syncing
|
|
60
|
+
- **Backup**: Automatic backups during deployment
|
|
61
|
+
|
|
62
|
+
### Deployment Strategies
|
|
63
|
+
|
|
64
|
+
Strategies determine how code gets deployed. Built-in strategies:
|
|
65
|
+
|
|
66
|
+
- **SSH**: Deploy via git pull on remote server
|
|
67
|
+
- **GitHub Pages**: Deploy static site to gh-pages branch
|
|
68
|
+
- **Custom**: Define your own (Jets, Docker, Kubernetes, etc.)
|
|
69
|
+
|
|
70
|
+
## Configuration
|
|
71
|
+
|
|
72
|
+
Create a `bard.rb` file in your project root:
|
|
73
|
+
|
|
74
|
+
```ruby
|
|
75
|
+
# Simple SSH deployment
|
|
76
|
+
target :production do
|
|
77
|
+
ssh "deploy@example.com:22",
|
|
78
|
+
path: "app",
|
|
79
|
+
gateway: "bastion@example.com:22"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# GitHub Pages static site
|
|
83
|
+
target :production do
|
|
84
|
+
github_pages "https://example.com"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Custom strategy (Jets serverless)
|
|
88
|
+
require_relative 'lib/jets_deploy_strategy'
|
|
89
|
+
|
|
90
|
+
target :production do
|
|
91
|
+
jets "https://api.example.com", run_tests: true
|
|
92
|
+
end
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Default Targets
|
|
96
|
+
|
|
97
|
+
Bard ships with default targets for Bot and Rose workflows. Override any in your `bard.rb`:
|
|
98
|
+
|
|
99
|
+
- **:local** - Local development (no SSH)
|
|
100
|
+
- **:ci** - Jenkins CI at staging.botandrose.com
|
|
101
|
+
- **:staging** - Staging server at staging.botandrose.com
|
|
102
|
+
- **:gubs** - Bot and Rose cloud server
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
# Override default staging to use Jets
|
|
106
|
+
target :staging do
|
|
107
|
+
jets "https://staging-api.example.com"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Keep :ci, :gubs, :local as defaults
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Commands
|
|
114
|
+
|
|
115
|
+
### Deployment
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Deploy to production
|
|
119
|
+
bard deploy production
|
|
120
|
+
|
|
121
|
+
# Deploy to staging
|
|
122
|
+
bard deploy staging
|
|
123
|
+
|
|
124
|
+
# Deploy feature branch to staging (no merge)
|
|
125
|
+
bard stage feature-branch
|
|
126
|
+
|
|
127
|
+
# Skip CI checks
|
|
128
|
+
bard deploy production --skip-ci
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Data Management
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# Copy database and assets from production to local
|
|
135
|
+
bard data --from=production --to=local
|
|
136
|
+
|
|
137
|
+
# Copy staging data to local
|
|
138
|
+
bard data --from=staging --to=local
|
|
139
|
+
|
|
140
|
+
# Configure additional paths to sync
|
|
141
|
+
# bard.rb:
|
|
142
|
+
data "public/uploads", "public/system"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### SSH Commands
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# SSH into a target
|
|
149
|
+
bard ssh production
|
|
150
|
+
|
|
151
|
+
# Run a command on a target
|
|
152
|
+
bard run production "bundle exec rails console"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### CI
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Run CI for current branch
|
|
159
|
+
bard ci
|
|
160
|
+
|
|
161
|
+
# Run tests locally
|
|
162
|
+
bard ci --local-ci
|
|
163
|
+
|
|
164
|
+
# Check CI status
|
|
165
|
+
bard ci --status
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Utilities
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
# Open target URL in browser
|
|
172
|
+
bard open production
|
|
173
|
+
|
|
174
|
+
# Ping target to check health
|
|
175
|
+
bard ping production
|
|
176
|
+
|
|
177
|
+
# Show uncommitted changes
|
|
178
|
+
bard hurt
|
|
179
|
+
|
|
180
|
+
# Open changed files in vim
|
|
181
|
+
bard vim
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Provisioning
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Full server provisioning
|
|
188
|
+
bard provision deploy@new-server.com:22
|
|
189
|
+
|
|
190
|
+
# Configure nginx for current app
|
|
191
|
+
bard setup
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## SSH Capability
|
|
195
|
+
|
|
196
|
+
Enable SSH to run commands and transfer files:
|
|
197
|
+
|
|
198
|
+
```ruby
|
|
199
|
+
target :production do
|
|
200
|
+
ssh "user@host:port",
|
|
201
|
+
path: "deploy/path",
|
|
202
|
+
gateway: "bastion@host:port",
|
|
203
|
+
ssh_key: "/path/to/key",
|
|
204
|
+
env: "RAILS_ENV=production"
|
|
205
|
+
end
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
This provides:
|
|
209
|
+
- `target.run!(command)` - Execute remote command (raises on error)
|
|
210
|
+
- `target.run(command)` - Execute remote command (silent on error)
|
|
211
|
+
- `target.exec!(command)` - Replace process with remote command
|
|
212
|
+
- `target.copy_file(path, to: target)` - Copy file to another target
|
|
213
|
+
- `target.copy_dir(path, to: target)` - Rsync directory to another target
|
|
214
|
+
|
|
215
|
+
## Deployment Strategies
|
|
216
|
+
|
|
217
|
+
### SSH Strategy
|
|
218
|
+
|
|
219
|
+
Deploy by running git pull on remote server:
|
|
220
|
+
|
|
221
|
+
```ruby
|
|
222
|
+
target :production do
|
|
223
|
+
ssh "deploy@example.com:22"
|
|
224
|
+
end
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Deployment runs: `git pull origin master && bin/setup`
|
|
228
|
+
|
|
229
|
+
### GitHub Pages Strategy
|
|
230
|
+
|
|
231
|
+
Deploy static site to GitHub Pages:
|
|
232
|
+
|
|
233
|
+
```ruby
|
|
234
|
+
target :production do
|
|
235
|
+
github_pages "https://example.com"
|
|
236
|
+
end
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Deployment:
|
|
240
|
+
1. Starts Rails server locally
|
|
241
|
+
2. Mirrors site with wget
|
|
242
|
+
3. Creates orphan commit with static assets
|
|
243
|
+
4. Force-pushes to `gh-pages` branch
|
|
244
|
+
|
|
245
|
+
### Custom Strategies
|
|
246
|
+
|
|
247
|
+
Create your own deployment strategy:
|
|
248
|
+
|
|
249
|
+
```ruby
|
|
250
|
+
# lib/jets_deploy_strategy.rb
|
|
251
|
+
module Bard
|
|
252
|
+
class DeployStrategy
|
|
253
|
+
class Jets < DeployStrategy
|
|
254
|
+
def deploy
|
|
255
|
+
target_name = target.key.to_s
|
|
256
|
+
options = target.strategy_options(:jets)
|
|
257
|
+
|
|
258
|
+
run! "rake vips:build:#{target_name}" unless options[:skip_build]
|
|
259
|
+
run! "bundle exec rspec" if should_run_tests?(target_name, options)
|
|
260
|
+
run! "jets deploy #{options[:env] || target_name}"
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
private
|
|
264
|
+
|
|
265
|
+
def should_run_tests?(target_name, options)
|
|
266
|
+
return options[:run_tests] if options.key?(:run_tests)
|
|
267
|
+
target_name == "production"
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Use it in your `bard.rb`:
|
|
275
|
+
|
|
276
|
+
```ruby
|
|
277
|
+
require_relative 'lib/jets_deploy_strategy'
|
|
278
|
+
|
|
279
|
+
target :production do
|
|
280
|
+
jets "https://api.example.com", run_tests: true
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
target :staging do
|
|
284
|
+
jets "https://staging-api.example.com", skip_build: true
|
|
285
|
+
end
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Strategies auto-register via Ruby's `inherited` hook - no manual registration needed!
|
|
289
|
+
|
|
290
|
+
## CI Configuration
|
|
291
|
+
|
|
292
|
+
Bard auto-detects your CI system:
|
|
293
|
+
- Finds `.github/workflows/ci.yml` → GitHub Actions
|
|
294
|
+
- Otherwise → Jenkins (legacy)
|
|
295
|
+
|
|
296
|
+
Override via DSL:
|
|
297
|
+
|
|
298
|
+
```ruby
|
|
299
|
+
# Force specific CI system
|
|
300
|
+
ci :github_actions
|
|
301
|
+
ci :jenkins
|
|
302
|
+
ci :local
|
|
303
|
+
|
|
304
|
+
# Disable CI
|
|
305
|
+
ci false
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## Ping Configuration
|
|
309
|
+
|
|
310
|
+
Configure health check URLs:
|
|
311
|
+
|
|
312
|
+
```ruby
|
|
313
|
+
target :production do
|
|
314
|
+
ssh "deploy@example.com:22"
|
|
315
|
+
ping "https://example.com", "/health", "/status"
|
|
316
|
+
end
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Auto-configured by deployment strategies:
|
|
320
|
+
|
|
321
|
+
```ruby
|
|
322
|
+
# Ping URL automatically set from Jets URL
|
|
323
|
+
target :production do
|
|
324
|
+
jets "https://api.example.com"
|
|
325
|
+
end
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Data Syncing
|
|
329
|
+
|
|
330
|
+
Database syncing is enabled by default when SSH is configured. Add file paths to sync:
|
|
331
|
+
|
|
332
|
+
```ruby
|
|
333
|
+
# Global configuration
|
|
334
|
+
data "public/uploads", "public/system"
|
|
335
|
+
|
|
336
|
+
target :production do
|
|
337
|
+
ssh "deploy@example.com:22"
|
|
338
|
+
end
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Then sync:
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
bard data --from=production --to=local
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
This:
|
|
348
|
+
1. Runs `bin/rake db:dump` on source
|
|
349
|
+
2. Copies `db/data.sql.gz` via SCP
|
|
350
|
+
3. Runs `bin/rake db:load` on destination
|
|
351
|
+
4. Rsyncs configured data paths
|
|
352
|
+
|
|
353
|
+
## Backup Configuration
|
|
354
|
+
|
|
355
|
+
Control whether backups are created during deployment:
|
|
356
|
+
|
|
357
|
+
```ruby
|
|
358
|
+
# Enable backups (default for SSH deployments)
|
|
359
|
+
backup true
|
|
360
|
+
|
|
361
|
+
# Disable backups (typical for serverless/static)
|
|
362
|
+
backup false
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## Example Configurations
|
|
366
|
+
|
|
367
|
+
### Traditional Rails App
|
|
368
|
+
|
|
369
|
+
```ruby
|
|
370
|
+
target :staging do
|
|
371
|
+
ssh "deploy@staging.example.com:22"
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
target :production do
|
|
375
|
+
ssh "deploy@production.example.com:22"
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
data "public/uploads"
|
|
379
|
+
backup true
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Serverless API (Jets)
|
|
383
|
+
|
|
384
|
+
```ruby
|
|
385
|
+
require_relative 'lib/jets_deploy_strategy'
|
|
386
|
+
|
|
387
|
+
target :staging do
|
|
388
|
+
jets "https://staging-api.example.com"
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
target :production do
|
|
392
|
+
jets "https://api.example.com", run_tests: true
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
backup false
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Hybrid (Jets + SSH for debugging)
|
|
399
|
+
|
|
400
|
+
```ruby
|
|
401
|
+
require_relative 'lib/jets_deploy_strategy'
|
|
402
|
+
|
|
403
|
+
target :staging do
|
|
404
|
+
jets "https://staging-api.example.com"
|
|
405
|
+
ssh "deploy@bastion.example.com:22" # Enables SSH commands
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
target :production do
|
|
409
|
+
jets "https://api.example.com"
|
|
410
|
+
# No SSH in production
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
backup false
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Static Site
|
|
417
|
+
|
|
418
|
+
```ruby
|
|
419
|
+
target :production do
|
|
420
|
+
github_pages "https://example.com"
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
backup false
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### Override Default Targets
|
|
427
|
+
|
|
428
|
+
```ruby
|
|
429
|
+
# Override default staging to use Jets
|
|
430
|
+
target :staging do
|
|
431
|
+
jets "https://staging-api.example.com"
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
# Keep :ci, :gubs, :local targets as defaults
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
## Migration from v1.x
|
|
438
|
+
|
|
439
|
+
See [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md) for detailed migration instructions.
|
|
440
|
+
|
|
441
|
+
Key changes in v2.0:
|
|
442
|
+
- `server` renamed to `target`
|
|
443
|
+
- SSH configuration uses hash options
|
|
444
|
+
- Strategy-first configuration
|
|
445
|
+
- Capability-based commands
|
|
446
|
+
|
|
447
|
+
## Architecture
|
|
448
|
+
|
|
449
|
+
Bard follows a modular, capability-based architecture:
|
|
450
|
+
|
|
451
|
+
- **Core**: Minimal git workflow and configuration
|
|
452
|
+
- **Capabilities**: Features enabled via DSL methods
|
|
453
|
+
- **Strategies**: Pluggable deployment strategies with auto-registration
|
|
454
|
+
- **Subsystems**: Independent and composable
|
|
455
|
+
|
|
456
|
+
See [ARCHITECTURE.md](ARCHITECTURE.md) for detailed architecture documentation.
|
|
457
|
+
|
|
458
|
+
## Custom Strategy Guide
|
|
459
|
+
|
|
460
|
+
See [CUSTOM_STRATEGIES.md](CUSTOM_STRATEGIES.md) for a step-by-step guide to creating custom deployment strategies.
|
|
461
|
+
|
|
462
|
+
## Development
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
# Clone repository
|
|
466
|
+
git clone https://github.com/botandrose/bard.git
|
|
467
|
+
cd bard
|
|
468
|
+
|
|
469
|
+
# Install dependencies
|
|
470
|
+
bundle install
|
|
471
|
+
|
|
472
|
+
# Run tests
|
|
473
|
+
bundle exec rspec
|
|
474
|
+
|
|
475
|
+
# Run bard from source
|
|
476
|
+
bundle exec bin/bard
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
## License
|
|
480
|
+
|
|
481
|
+
MIT License. Copyright (c) 2018 Micah Geisel. See LICENSE for details.
|
|
482
|
+
|
|
483
|
+
## Contributing
|
|
484
|
+
|
|
485
|
+
1. Fork it
|
|
486
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
487
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
488
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
489
|
+
5. Create new Pull Request
|
data/lib/bard/cli/deploy.rb
CHANGED
|
@@ -44,10 +44,19 @@ module Bard::CLI::Deploy
|
|
|
44
44
|
invoke :master_key, [], from: "local", to: to
|
|
45
45
|
config[to].run! "bin/setup && bard setup"
|
|
46
46
|
else
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
# Use deployment strategy for v2.0 Targets, or fallback for v1.x Servers
|
|
48
|
+
target = config[to]
|
|
49
|
+
if target.respond_to?(:deploy_strategy) && target.deploy_strategy
|
|
50
|
+
require "bard/deploy_strategy/#{target.deploy_strategy}"
|
|
51
|
+
strategy = target.deploy_strategy_instance
|
|
52
|
+
strategy.deploy
|
|
53
|
+
elsif target.respond_to?(:github_pages) && target.github_pages
|
|
54
|
+
# Old v1.x github_pages support
|
|
55
|
+
require "bard/github_pages"
|
|
56
|
+
Bard::GithubPages.new(self).deploy(target)
|
|
49
57
|
else
|
|
50
|
-
|
|
58
|
+
# Default SSH deployment
|
|
59
|
+
target.run! "git pull origin master && bin/setup"
|
|
51
60
|
end
|
|
52
61
|
end
|
|
53
62
|
|
data/lib/bard/command.rb
CHANGED
|
@@ -24,8 +24,14 @@ module Bard
|
|
|
24
24
|
|
|
25
25
|
def run verbose: false, quiet: false
|
|
26
26
|
# no-op if server doesn't really exist
|
|
27
|
-
if on.to_sym != :local
|
|
28
|
-
|
|
27
|
+
if on.to_sym != :local
|
|
28
|
+
# Check for new Target architecture
|
|
29
|
+
if on.respond_to?(:server) && on.server.nil?
|
|
30
|
+
return true
|
|
31
|
+
# Check for old Server architecture
|
|
32
|
+
elsif on.respond_to?(:ssh) && on.ssh == false
|
|
33
|
+
return true
|
|
34
|
+
end
|
|
29
35
|
end
|
|
30
36
|
if verbose
|
|
31
37
|
system full_command(quiet: quiet)
|
|
@@ -55,18 +61,28 @@ module Bard
|
|
|
55
61
|
end
|
|
56
62
|
|
|
57
63
|
def remote_command quiet: false
|
|
64
|
+
# Support both new Target (with server attribute) and old Server architecture
|
|
65
|
+
ssh_server = on.respond_to?(:server) ? on.server : on
|
|
66
|
+
|
|
58
67
|
cmd = command
|
|
59
|
-
if
|
|
60
|
-
cmd = "#{
|
|
68
|
+
if ssh_server.env
|
|
69
|
+
cmd = "#{ssh_server.env} #{command}"
|
|
61
70
|
end
|
|
62
71
|
unless home
|
|
63
|
-
|
|
72
|
+
path = on.respond_to?(:path) ? on.path : ssh_server.path
|
|
73
|
+
cmd = "cd #{path} && #{cmd}" if path
|
|
64
74
|
end
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
75
|
+
|
|
76
|
+
ssh_key = ssh_server.ssh_key ? "-i #{ssh_server.ssh_key} " : ""
|
|
77
|
+
ssh_uri = ssh_server.respond_to?(:ssh_uri) ? ssh_server.ssh_uri : ssh_server.ssh_uri(:ssh)
|
|
78
|
+
|
|
79
|
+
cmd = "ssh -tt #{ssh_key} #{ssh_uri} '#{cmd}'"
|
|
80
|
+
|
|
81
|
+
if ssh_server.gateway
|
|
82
|
+
gateway_uri = ssh_server.respond_to?(:ssh_uri) ? ssh_server.gateway : ssh_server.ssh_uri(:gateway)
|
|
83
|
+
cmd = "ssh -tt #{gateway_uri} \"#{cmd}\""
|
|
69
84
|
end
|
|
85
|
+
|
|
70
86
|
cmd += " 2>&1" if quiet
|
|
71
87
|
cmd
|
|
72
88
|
end
|