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.
data/ARCHITECTURE.md ADDED
@@ -0,0 +1,957 @@
1
+ # Bard 2.0.0 Architecture
2
+
3
+ ## Vision
4
+
5
+ A modular deployment tool where:
6
+ - **Core** provides minimal git workflow and configuration
7
+ - **Capabilities** are enabled via DSL methods
8
+ - **Deployment strategies** are pluggable and auto-registered
9
+ - **Subsystems** are independent and composable
10
+
11
+ ## Core Concepts
12
+
13
+ ### Target
14
+ A deployment destination. Targets are strategy-agnostic and capability-based.
15
+
16
+ ### Capability
17
+ A feature enabled on a target (e.g., SSH, database, file copying, CI).
18
+
19
+ ### Deployment Strategy
20
+ How code gets deployed to a target. Strategies are pluggable and auto-register via `inherited` hook.
21
+
22
+ ## Subsystems
23
+
24
+ ### 1. Core (always enabled)
25
+ **Files:**
26
+ - `lib/bard/config.rb` - Configuration DSL
27
+ - `lib/bard/target.rb` - Target (formerly Server) definition
28
+ - `lib/bard/git.rb` - Git utilities
29
+ - `lib/bard/cli.rb` - CLI framework
30
+ - `lib/bard/deploy_strategy.rb` - Base strategy class with auto-registration
31
+ - `lib/bard/default_config.rb` - Default target configurations
32
+
33
+ **Responsibilities:**
34
+ - Load default configuration
35
+ - Load and evaluate `bard.rb` (overrides defaults)
36
+ - Provide target registry
37
+ - Git workflow (branching, merging, fast-forward checks)
38
+ - Deployment strategy auto-registration
39
+
40
+ **DSL:**
41
+ ```ruby
42
+ target :production do
43
+ # DSL methods enable capabilities
44
+ end
45
+ ```
46
+
47
+ **Commands:**
48
+ - `bard deploy` - Core git workflow + delegates to strategy
49
+ - `bard hurt` - Show uncommitted changes (git-based, no target needed)
50
+ - `bard vim` - Open changed files in vim (git-based, no target needed)
51
+
52
+ **Default Targets:**
53
+ Defined in `lib/bard/default_config.rb` (can be overridden in `bard.rb`):
54
+ - `:local` - No SSH, path `./`, ping `#{project_name}.local`
55
+ - `:ci` - Jenkins at `staging.botandrose.com`
56
+ - `:staging` - SSH to `staging.botandrose.com`
57
+ - `:gubs` - SSH to Bot and Rose cloud server
58
+
59
+ ---
60
+
61
+ ### 2. SSH Capability
62
+ **Files:**
63
+ - `lib/bard/ssh_server.rb` - SSH connection abstraction
64
+ - `lib/bard/command.rb` - Remote command execution
65
+ - `lib/bard/copy.rb` - SCP/rsync file transfer
66
+
67
+ **Enabled by:**
68
+ ```ruby
69
+ target :production do
70
+ ssh "user@host:port",
71
+ path: "deploy/path",
72
+ gateway: "bastion@host:port",
73
+ ssh_key: "/path/to/key",
74
+ env: "RAILS_ENV=production"
75
+ end
76
+ ```
77
+
78
+ **Provides:**
79
+ - `target.server` - Access to SSHServer object
80
+ - `target.run!(cmd)` - Execute remote command
81
+ - `target.run(cmd)` - Execute remote command (no exception on failure)
82
+ - `target.exec!(cmd)` - Replace current process with remote command
83
+ - `target.copy_file(path, to:)` - Copy file to another target
84
+ - `target.copy_dir(path, to:)` - Rsync directory to another target
85
+
86
+ **Commands enabled:**
87
+ - `bard ssh [target]` - SSH into target
88
+ - `bard run [target] "command"` - Run command on target
89
+
90
+ **Auto-configuration:**
91
+ - Sets ping URL from hostname
92
+
93
+ **Error handling:**
94
+ - Commands that require SSH fail with clear message if capability not enabled
95
+
96
+ ---
97
+
98
+ ### 3. Deployment Strategies
99
+
100
+ #### SSH Strategy (built-in)
101
+ **File:** `lib/bard/deploy_strategy/ssh.rb`
102
+
103
+ **Enabled by:**
104
+ ```ruby
105
+ target :production do
106
+ ssh "user@host:port"
107
+ end
108
+ ```
109
+
110
+ **Deployment behavior:**
111
+ 1. Runs `git pull origin master && bin/setup` on remote server
112
+
113
+ **Requires:** SSH capability
114
+
115
+ ---
116
+
117
+ #### GitHub Pages Strategy (built-in)
118
+ **File:** `lib/bard/deploy_strategy/github_pages.rb`
119
+
120
+ **Enabled by:**
121
+ ```ruby
122
+ target :production do
123
+ github_pages "https://example.com"
124
+ end
125
+ ```
126
+
127
+ **Deployment behavior:**
128
+ 1. Starts Rails server locally
129
+ 2. Mirrors site with wget
130
+ 3. Creates orphan commit with static assets
131
+ 4. Force-pushes to `gh-pages` branch
132
+
133
+ **Requires:** None (runs locally)
134
+
135
+ ---
136
+
137
+ #### Custom Strategies (user-defined)
138
+ **Example:** Jets deployment (lives in crucible project)
139
+
140
+ ```ruby
141
+ # In crucible project: lib/jets_deploy_strategy.rb
142
+ module Bard
143
+ class DeployStrategy
144
+ class Jets < DeployStrategy
145
+ def deploy
146
+ target_name = target.key.to_s
147
+ options = target.strategy_options(:jets)
148
+
149
+ run! "rake vips:build:#{target_name}" unless options[:skip_build]
150
+ run! "bundle exec rspec" if should_run_tests?(target_name, options)
151
+ run! "jets deploy #{options[:env] || target_name}"
152
+ end
153
+
154
+ private
155
+
156
+ def should_run_tests?(target_name, options)
157
+ return options[:run_tests] if options.key?(:run_tests)
158
+ target_name == "production"
159
+ end
160
+ end
161
+ end
162
+ end
163
+ ```
164
+
165
+ **Usage:**
166
+ ```ruby
167
+ # In crucible/bard.rb
168
+ require_relative 'lib/jets_deploy_strategy'
169
+
170
+ target :production do
171
+ jets "https://api.example.com", run_tests: true
172
+ end
173
+ ```
174
+
175
+ **Auto-registered:** ✅ Via `DeployStrategy.inherited` hook
176
+
177
+ ---
178
+
179
+ ### 4. CI Capability
180
+ **Files:**
181
+ - `lib/bard/ci.rb` - CI abstraction
182
+ - `lib/bard/ci/local.rb` - Local test runner
183
+ - `lib/bard/ci/jenkins.rb` - Jenkins integration
184
+ - `lib/bard/ci/github_actions.rb` - GitHub Actions integration
185
+
186
+ **Auto-enabled:** Based on detection:
187
+ - `.github/workflows/ci.yml` exists → GitHub Actions
188
+ - Otherwise → Jenkins (legacy)
189
+
190
+ **Override via DSL:**
191
+ ```ruby
192
+ # Force specific CI system
193
+ ci :github_actions
194
+ ci :jenkins
195
+ ci :local
196
+
197
+ # Disable CI
198
+ ci false
199
+ ```
200
+
201
+ **Commands:**
202
+ - `bard ci [branch]` - Run CI checks
203
+ - `--local-ci` - Run tests locally
204
+ - `--status` - Check CI status
205
+ - `--resume` - Resume existing CI build
206
+
207
+ **Used by:** `bard deploy` (unless `--skip-ci`)
208
+
209
+ ---
210
+
211
+ ### 5. Data Capability
212
+ **Files:**
213
+ - `lib/bard/cli/data.rb` - Data sync command
214
+
215
+ **Enabled by:**
216
+ Database syncing is enabled by default, provided that SSH capability exists on both source and destination targets. The `data` DSL configures additional file paths to sync with rsync.
217
+ ```ruby
218
+ # Global configuration (applies to all targets)
219
+ data "public/uploads", "public/system"
220
+ ```
221
+
222
+ **Commands enabled:**
223
+ - `bard data --from=production --to=local` - Copy database and assets
224
+
225
+ **Behavior:**
226
+ 1. Runs `bin/rake db:dump` on source target
227
+ 2. Copies `db/data.sql.gz` via SCP
228
+ 3. Runs `bin/rake db:load` on destination target
229
+ 4. Rsyncs each configured data path if configured
230
+
231
+ **Requires:**
232
+ - SSH capability on both source and destination targets
233
+
234
+ **Opitional:**
235
+ - Additional data paths to rsync configured via `data` DSL
236
+
237
+ **Safety:**
238
+ - Warns when pushing to production
239
+ - Requires confirmation with full production URL
240
+
241
+ ---
242
+
243
+ ### 6. Backup Capability
244
+ **Enabled by:**
245
+ ```ruby
246
+ # Global configuration
247
+ backup true # Enable backups (default for SSH deployments)
248
+ backup false # Disable backups (typical for serverless/static)
249
+ ```
250
+
251
+ **Purpose:**
252
+ Controls whether database backups are created during deployment/provisioning.
253
+
254
+ **Used by:**
255
+ - Deployment process
256
+ - Provisioning scripts
257
+
258
+ **Separate from:** Data capability (backup is about creating backups, data is about syncing)
259
+
260
+ **Requires:** SSH capability (backups are stored on remote servers)
261
+
262
+ ---
263
+
264
+ ### 7. Master Key Capability
265
+ **Files:**
266
+ - `lib/bard/cli/master_key.rb` - Master key sync
267
+
268
+ **Commands:**
269
+ - `bard master_key --from=production --to=local` - Copy Rails master key
270
+
271
+ **Behavior:**
272
+ - Copies `config/master.key` via SCP between targets
273
+
274
+ **Requires:** SSH capability on both source and destination targets
275
+
276
+ **Used by:**
277
+ - `bard provision` (initial setup)
278
+ - Manual key distribution
279
+
280
+ ---
281
+
282
+ ### 8. Staging Capability
283
+ **Commands:**
284
+ - `bard stage [branch]` - Deploy feature branch to staging without merge
285
+
286
+ **Behavior:**
287
+ 1. Pushes branch to origin
288
+ 2. Checks out branch on staging server via SSH
289
+ 3. Runs `bin/setup`
290
+ 4. Pings staging
291
+
292
+ **Requires:**
293
+ - SSH capability on `:staging` target
294
+ - `:production` target must be defined (otherwise use `bard deploy staging`)
295
+
296
+ ---
297
+
298
+ ### 9. Ping Capability
299
+ **Enabled by:**
300
+ ```ruby
301
+ target :production do
302
+ ping "https://example.com"
303
+ ping "/health", "/status" # Multiple paths
304
+ end
305
+ ```
306
+
307
+ **Auto-enabled by:** Deployment strategies that provide URLs
308
+
309
+ **Commands:**
310
+ - `bard ping [target]` - Check if URLs respond
311
+
312
+ **Behavior:**
313
+ - Makes HTTP requests to ping URLs
314
+ - Follows redirects
315
+ - Exits with error if any URL is down
316
+
317
+ **Used by:** `bard deploy` (after successful deployment)
318
+
319
+ ---
320
+
321
+ ### 10. Provisioning (Separate Command)
322
+ **Files:**
323
+ - `lib/bard/provision.rb` - Provision orchestration
324
+ - `lib/bard/provision/*.rb` - Individual provisioning steps
325
+
326
+ **Commands:**
327
+ - `bard setup` - Configure nginx for current app
328
+ - `bard provision [ssh_url]` - Full server provisioning
329
+
330
+ **Provisioning steps:**
331
+ 1. SSH - Configure SSH access
332
+ 2. User - Create deployment user
333
+ 3. AuthorizedKeys - Install SSH keys
334
+ 4. Swapfile - Create swap
335
+ 5. Apt - Install system packages
336
+ 6. MySQL - Install and configure MySQL
337
+ 7. Repo - Clone git repository
338
+ 8. MasterKey - Install Rails master key
339
+ 9. RVM - Install Ruby
340
+ 10. App - Bundle and setup app
341
+ 11. Passenger - Install Passenger
342
+ 12. HTTP - Configure nginx
343
+ 13. LogRotation - Configure log rotation
344
+ 14. Data - Import initial data (if backup enabled)
345
+ 15. Deploy - Initial deployment
346
+
347
+ **Requires:** SSH capability on target
348
+
349
+ **Note:** Provisioning is a one-time server setup command, not a deployment capability
350
+
351
+ ---
352
+
353
+ ### 11. Open Capability
354
+ **Commands:**
355
+ - `bard open [target]` - Open target URL in browser
356
+
357
+ **Behavior:**
358
+ - Uses `ping` URL from target configuration
359
+ - Opens in system default browser
360
+
361
+ **Requires:** Ping URL configured on target
362
+
363
+ ---
364
+
365
+ ## Capability Dependency Tree
366
+
367
+ ```
368
+ Core (always enabled)
369
+ ├── Git workflow
370
+ ├── Target registry
371
+ └── Strategy auto-registration
372
+
373
+ SSH Capability
374
+ ├── Enables: run!, run, exec!, copy_file, copy_dir
375
+ ├── Required by: SSH strategy, backup, data, master_key, provisioning
376
+ └── Commands: bard ssh, bard run
377
+
378
+ CI Capability
379
+ ├── Auto-detected (github actions / jenkins)
380
+ ├── Overridable via DSL
381
+ └── Used by: bard deploy (unless --skip-ci)
382
+
383
+ Data Capability
384
+ ├── Requires: SSH on both targets
385
+ └── Commands: bard data
386
+
387
+ Backup Capability
388
+ ├── Requires: SSH
389
+ └── Used by: deployment, provisioning
390
+
391
+ Master Key Capability
392
+ ├── Requires: SSH on both targets
393
+ └── Commands: bard master_key
394
+
395
+ Ping Capability
396
+ ├── Auto-configured by deployment strategies
397
+ └── Commands: bard ping, bard open
398
+
399
+ Deployment Strategies
400
+ ├── SSH: requires SSH capability
401
+ ├── GitHub Pages: no requirements
402
+ └── Custom (Jets, Docker, etc.): defined by user
403
+ ```
404
+
405
+ ---
406
+
407
+ ## Modular Architecture
408
+
409
+ ### Capability Registration
410
+
411
+ Capabilities are enabled implicitly via DSL methods:
412
+
413
+ ```ruby
414
+ # Enable SSH capability
415
+ ssh "user@host"
416
+
417
+ # Enable GitHub Pages deployment
418
+ github_pages "https://example.com"
419
+
420
+ # Enable data sync
421
+ data "public/uploads"
422
+
423
+ # Enable/disable backups
424
+ backup true
425
+ ```
426
+
427
+ ### Capability Detection
428
+
429
+ Commands check for capabilities before executing:
430
+
431
+ ```ruby
432
+ # In bard/cli/data.rb
433
+ def data
434
+ from = config[options[:from]]
435
+ to = config[options[:to]]
436
+
437
+ # Will raise "SSH not configured for this target" if capability missing
438
+ from.run! "bin/rake db:dump"
439
+ from.copy_file "db/data.sql.gz", to: to
440
+ to.run! "bin/rake db:load"
441
+
442
+ # Only sync if data paths configured
443
+ config.data.each do |path|
444
+ from.copy_dir path, to: to
445
+ end
446
+ end
447
+ ```
448
+
449
+ ### Strategy Auto-Registration
450
+
451
+ ```ruby
452
+ # In lib/bard/deploy_strategy.rb
453
+ class DeployStrategy
454
+ @strategies = {}
455
+
456
+ def self.inherited(subclass)
457
+ name = extract_strategy_name(subclass)
458
+ strategies[name] = subclass
459
+ end
460
+ end
461
+
462
+ # User defines custom strategy
463
+ class DeployStrategy::Docker < DeployStrategy
464
+ def deploy
465
+ # ...
466
+ end
467
+ end
468
+ # Automatically registers as :docker strategy
469
+ ```
470
+
471
+ ### Dynamic DSL Methods
472
+
473
+ ```ruby
474
+ # In lib/bard/target.rb
475
+ def method_missing(method, *args, **kwargs)
476
+ if Bard::DeployStrategy[method]
477
+ enable_strategy(method, *args, **kwargs)
478
+ else
479
+ super
480
+ end
481
+ end
482
+ ```
483
+
484
+ This allows any registered strategy to be used as a DSL method without modifying Target class.
485
+
486
+ ### Default Configuration
487
+
488
+ ```ruby
489
+ # lib/bard/default_config.rb
490
+ module Bard
491
+ DEFAULT_CONFIG = proc do |project_name|
492
+ target :local do
493
+ ssh false
494
+ path "./"
495
+ ping "#{project_name}.local"
496
+ end
497
+
498
+ target :ci do
499
+ ssh "jenkins@staging.botandrose.com:22022"
500
+ path "jobs/#{project_name}/workspace"
501
+ ping false
502
+ end
503
+
504
+ target :staging do
505
+ ssh "www@staging.botandrose.com:22022"
506
+ path project_name
507
+ ping "#{project_name}.botandrose.com"
508
+ end
509
+
510
+ target :gubs do
511
+ ssh "botandrose@cloud.hackett.world:22022"
512
+ path "Sites/#{project_name}"
513
+ ping false
514
+ end
515
+ end
516
+ end
517
+ ```
518
+
519
+ Loaded before user's `bard.rb`, so user can override any default target.
520
+
521
+ ---
522
+
523
+ ## Migration Path (1.x → 2.0.0)
524
+
525
+ ### Breaking Changes
526
+
527
+ 1. **`server` renamed to `target`**
528
+ - Rationale: More accurate for serverless deployments
529
+ - Migration: `server` is aliased to `target` for compatibility (deprecated)
530
+
531
+ 2. **SSH configuration changes**
532
+ ```ruby
533
+ # Old (1.x)
534
+ server :production do
535
+ ssh "user@host:port"
536
+ path "deploy/path"
537
+ gateway "bastion@host:port"
538
+ end
539
+
540
+ # New (2.0)
541
+ target :production do
542
+ ssh "user@host:port",
543
+ path: "deploy/path",
544
+ gateway: "bastion@host:port"
545
+ end
546
+ ```
547
+
548
+ 3. **Strategy-first configuration**
549
+ ```ruby
550
+ # Old (1.x)
551
+ server :production do
552
+ github_pages true
553
+ ping "https://example.com"
554
+ end
555
+
556
+ # New (2.0)
557
+ target :production do
558
+ github_pages "https://example.com" # Sets both strategy and ping
559
+ end
560
+ ```
561
+
562
+ ### Deprecation Warnings
563
+
564
+ Version 1.9.x can include deprecation warnings for:
565
+ - Using `server` instead of `target`
566
+ - Old-style SSH configuration
567
+ - Old-style strategy configuration
568
+
569
+ ---
570
+
571
+ ## Benefits of New Architecture
572
+
573
+ 1. **Modularity**: Capabilities are independent and composable
574
+ 2. **Extensibility**: Custom deployment strategies without gem modification
575
+ 3. **Clarity**:
576
+ - `target` vs `server` distinction
577
+ - Clear capability dependencies (e.g., "data requires SSH")
578
+ 4. **Auto-registration**: Strategies register themselves via Ruby's `inherited` hook
579
+ 5. **Type safety**: Commands fail fast with clear messages if capability not enabled
580
+ 6. **Flexibility**: Mix capabilities (e.g., Jets + SSH for debugging)
581
+ 7. **Simplicity**: Default case is concise and clear
582
+ 8. **Organization-specific**: Ships with Bot and Rose defaults, easily overridden
583
+
584
+ ---
585
+
586
+ ## Example Configurations
587
+
588
+ ### Traditional Rails App
589
+ ```ruby
590
+ target :staging do
591
+ ssh "deploy@staging.example.com:22"
592
+ end
593
+
594
+ target :production do
595
+ ssh "deploy@production.example.com:22"
596
+ end
597
+
598
+ data "public/uploads"
599
+ backup true
600
+ ```
601
+
602
+ ### Serverless API (Jets)
603
+ ```ruby
604
+ require_relative 'lib/jets_deploy_strategy'
605
+
606
+ target :staging do
607
+ jets "https://staging-api.example.com"
608
+ end
609
+
610
+ target :production do
611
+ jets "https://api.example.com", run_tests: true
612
+ end
613
+
614
+ backup false
615
+ ```
616
+
617
+ ### Hybrid (Jets + SSH for debugging)
618
+ ```ruby
619
+ require_relative 'lib/jets_deploy_strategy'
620
+
621
+ target :staging do
622
+ jets "https://staging-api.example.com"
623
+ ssh "deploy@bastion.example.com:22" # Enables SSH commands for debugging
624
+ end
625
+
626
+ target :production do
627
+ jets "https://api.example.com"
628
+ # No SSH in production
629
+ end
630
+
631
+ backup false
632
+ ```
633
+
634
+ ### Static Site
635
+ ```ruby
636
+ target :production do
637
+ github_pages "https://example.com"
638
+ end
639
+
640
+ backup false
641
+ ```
642
+
643
+ ### Override Default Targets
644
+ ```ruby
645
+ # Override default staging configuration
646
+ target :staging do
647
+ jets "https://staging-api.example.com"
648
+ end
649
+
650
+ # Keep default :ci, :gubs, :local targets as-is
651
+ ```
652
+
653
+ ### Custom CI Configuration
654
+ ```ruby
655
+ # Force local CI (ignore GitHub Actions)
656
+ ci :local
657
+
658
+ # Or disable CI entirely
659
+ ci false
660
+ ```
661
+
662
+ ---
663
+
664
+ ## Implementation Checklist
665
+
666
+ ### Phase 1: Documentation (Write the Spec)
667
+ **Goal:** Document the v2.0.0 API completely before implementation
668
+
669
+ - [ ] Update README.md with v2 API (already done)
670
+ - [ ] Finalize ARCHITECTURE.md (this file)
671
+ - [ ] Create MIGRATION_GUIDE.md (v1 → v2)
672
+ - [ ] Document all breaking changes
673
+ - [ ] Provide migration examples for each change
674
+ - [ ] Include automated migration scripts if possible
675
+ - [ ] Document custom strategy creation
676
+ - [ ] Step-by-step guide
677
+ - [ ] Example implementations (Docker, Kubernetes, etc.)
678
+ - [ ] Auto-registration explanation
679
+ - [ ] Document capability dependencies
680
+ - [ ] Capability dependency tree diagram
681
+ - [ ] Error messages for missing capabilities
682
+ - [ ] Add examples for all common use cases
683
+ - [ ] Traditional Rails app
684
+ - [ ] Serverless (Jets, Lambda)
685
+ - [ ] Static sites (GitHub Pages)
686
+ - [ ] Hybrid deployments
687
+ - [ ] Document default targets and how to override
688
+
689
+ **Success criteria:**
690
+ - Documentation is comprehensive and clear
691
+ - All v2 features are documented
692
+ - Migration path is well-explained
693
+ - Examples cover common use cases
694
+
695
+ ---
696
+
697
+ ### Phase 2: Testing (TDD - Write Failing Tests)
698
+ **Goal:** Write comprehensive tests that define v2.0.0 behavior
699
+
700
+ - [ ] Test capability system
701
+ - [ ] Capabilities are enabled by DSL methods
702
+ - [ ] Capabilities are checked before command execution
703
+ - [ ] Clear error messages when capability missing
704
+ - [ ] Test strategy auto-registration
705
+ - [ ] Strategies auto-register via `inherited` hook
706
+ - [ ] Strategy name extraction from class name
707
+ - [ ] Strategy retrieval from registry
708
+ - [ ] Test dynamic DSL methods
709
+ - [ ] `method_missing` enables strategies
710
+ - [ ] Auto-configuration of ping URLs
711
+ - [ ] Strategy options storage
712
+ - [ ] Test default configuration
713
+ - [ ] Defaults load before user config
714
+ - [ ] User can override defaults
715
+ - [ ] Default targets work as expected
716
+ - [ ] Test Target (formerly Server)
717
+ - [ ] `target` DSL method creates targets
718
+ - [ ] `server` DSL method works with deprecation (v1.9.x)
719
+ - [ ] SSH configuration with hash options
720
+ - [ ] Capability tracking
721
+ - [ ] Test SSH capability
722
+ - [ ] SSHServer creation
723
+ - [ ] run!, run, exec! methods
724
+ - [ ] copy_file, copy_dir methods
725
+ - [ ] Error when SSH not configured
726
+ - [ ] Test deployment strategies
727
+ - [ ] SSH strategy requires SSH capability
728
+ - [ ] GitHub Pages strategy runs locally
729
+ - [ ] Custom strategy auto-registers
730
+ - [ ] Test data capability
731
+ - [ ] Database sync works with SSH
732
+ - [ ] Additional paths sync if configured
733
+ - [ ] Error when SSH missing on source/destination
734
+ - [ ] Test CI capability
735
+ - [ ] Auto-detection (GitHub Actions vs Jenkins)
736
+ - [ ] Manual override via DSL
737
+ - [ ] Disable via `ci false`
738
+ - [ ] Integration tests
739
+ - [ ] Full deployment workflows
740
+ - [ ] Multi-target data copying
741
+ - [ ] Strategy-specific deployments
742
+
743
+ **Success criteria:**
744
+ - All tests fail (features not implemented yet)
745
+ - Tests clearly define expected behavior
746
+ - Edge cases are covered
747
+ - Error scenarios are tested
748
+
749
+ ---
750
+
751
+ ### Phase 3: Core Refactoring
752
+ **Goal:** Implement core v2.0.0 architecture
753
+
754
+ - [ ] Rename `Server` to `Target`
755
+ - [ ] Create `lib/bard/target.rb`
756
+ - [ ] Migrate code from `lib/bard/server.rb`
757
+ - [ ] Keep `server.rb` as alias for compatibility
758
+ - [ ] Implement capability tracking system
759
+ - [ ] `enable_capability(name)` method
760
+ - [ ] `has_capability?(name)` method
761
+ - [ ] `require_capability!(name)` with clear errors
762
+ - [ ] Add `DeployStrategy` base class with auto-registration
763
+ - [ ] Create `lib/bard/deploy_strategy.rb`
764
+ - [ ] Implement `inherited` hook for auto-registration
765
+ - [ ] Strategy name extraction from class name
766
+ - [ ] Strategy registry (`DeployStrategy.strategies`)
767
+ - [ ] Extract default configuration
768
+ - [ ] Create `lib/bard/default_config.rb`
769
+ - [ ] Move default targets from Config initialization
770
+ - [ ] Load defaults before user config
771
+ - [ ] Update `Config` class
772
+ - [ ] Load default config first
773
+ - [ ] Then load user `bard.rb`
774
+ - [ ] Support `target` DSL method
775
+ - [ ] Keep `server` alias with deprecation
776
+
777
+ **Success criteria:**
778
+ - Tests for core features pass
779
+ - Capability tracking works
780
+ - Strategies auto-register
781
+ - Default config can be overridden
782
+
783
+ ---
784
+
785
+ ### Phase 4: SSH Capability
786
+ **Goal:** Refactor SSH into a capability
787
+
788
+ - [ ] Extract SSH connection to `SSHServer` class
789
+ - [ ] Create `lib/bard/ssh_server.rb`
790
+ - [ ] Move SSH-specific methods from Target
791
+ - [ ] URI parsing and connection strings
792
+ - [ ] Update `ssh` DSL method
793
+ - [ ] Accept hash options (path, gateway, ssh_key, env)
794
+ - [ ] Create SSHServer instance
795
+ - [ ] Enable SSH capability
796
+ - [ ] Auto-configure ping from hostname
797
+ - [ ] Add capability checks
798
+ - [ ] `run!` requires SSH capability
799
+ - [ ] `copy_file` requires SSH capability
800
+ - [ ] `copy_dir` requires SSH capability
801
+ - [ ] Clear error messages when SSH missing
802
+ - [ ] Update commands to check SSH capability
803
+ - [ ] `bard ssh` requires SSH
804
+ - [ ] `bard run` requires SSH
805
+ - [ ] Error message: "SSH not configured for this target"
806
+
807
+ **Success criteria:**
808
+ - SSH tests pass
809
+ - SSH is properly isolated as a capability
810
+ - Error messages are clear
811
+ - Commands fail gracefully without SSH
812
+
813
+ ---
814
+
815
+ ### Phase 5: Strategy Extraction
816
+ **Goal:** Extract deployment strategies into separate classes
817
+
818
+ - [ ] Create `DeployStrategy::SSH`
819
+ - [ ] Move SSH deployment logic
820
+ - [ ] `git pull origin master && bin/setup`
821
+ - [ ] Require SSH capability
822
+ - [ ] Create `DeployStrategy::GithubPages`
823
+ - [ ] Move GitHub Pages deployment logic
824
+ - [ ] Static site building
825
+ - [ ] Git commit and push to gh-pages
826
+ - [ ] Update `deploy.rb` to use strategy registry
827
+ - [ ] Look up strategy from registry
828
+ - [ ] Instantiate and call `deploy`
829
+ - [ ] Error if strategy not found
830
+ - [ ] Add `method_missing` to Target
831
+ - [ ] Check if method is registered strategy
832
+ - [ ] Enable capability and set deploy_strategy
833
+ - [ ] Store options for strategy
834
+ - [ ] Auto-configure ping URL
835
+
836
+ **Success criteria:**
837
+ - Strategy tests pass
838
+ - Deployment strategies are isolated
839
+ - Dynamic DSL methods work
840
+ - Custom strategies can be registered
841
+
842
+ ---
843
+
844
+ ### Phase 6: Capability Commands
845
+ **Goal:** Update all commands to be capability-aware
846
+
847
+ - [ ] Update `data` command
848
+ - [ ] Database sync always available with SSH
849
+ - [ ] `data` DSL only adds optional file paths
850
+ - [ ] Check SSH capability on source and destination
851
+ - [ ] Clear error when SSH missing
852
+ - [ ] Update `master_key` command
853
+ - [ ] Require SSH on source and destination
854
+ - [ ] Clear error when SSH missing
855
+ - [ ] Update `backup` capability
856
+ - [ ] Separate from `data`
857
+ - [ ] Controls whether backups are created
858
+ - [ ] Requires SSH (backups stored on servers)
859
+ - [ ] Add CI configuration DSL
860
+ - [ ] `ci :github_actions` - force GitHub Actions
861
+ - [ ] `ci :jenkins` - force Jenkins
862
+ - [ ] `ci :local` - run locally
863
+ - [ ] `ci false` - disable CI
864
+ - [ ] Auto-detect by default
865
+ - [ ] Update all remaining commands
866
+ - [ ] `bard stage` requires SSH on staging
867
+ - [ ] `bard ping` requires ping URLs
868
+ - [ ] `bard open` requires ping URLs
869
+ - [ ] `bard provision` requires SSH
870
+ - [ ] Add clear error messages
871
+ - [ ] "SSH not configured for this target"
872
+ - [ ] "Ping URL not configured for this target"
873
+ - [ ] "CI is disabled for this project"
874
+
875
+ **Success criteria:**
876
+ - All capability tests pass
877
+ - Commands check capabilities properly
878
+ - Error messages are helpful
879
+ - No regressions in functionality
880
+
881
+ ---
882
+
883
+ ### Phase 7: v1.9.x Transitional Release (Dual API Support)
884
+ **Goal:** Support both v1 and v2 APIs simultaneously with deprecation warnings
885
+
886
+ - [ ] Add deprecation warning infrastructure
887
+ - [ ] Support both `server` and `target` DSL methods
888
+ - [ ] `target` is the new primary method
889
+ - [ ] `server` calls `target` with deprecation warning
890
+ - [ ] Support both old and new SSH configuration styles
891
+ ```ruby
892
+ # v1 style (deprecated, still works)
893
+ target :production do
894
+ ssh "user@host:port"
895
+ path "deploy/path"
896
+ gateway "bastion@host"
897
+ end
898
+
899
+ # v2 style (preferred)
900
+ target :production do
901
+ ssh "user@host:port", path: "deploy/path", gateway: "bastion@host"
902
+ end
903
+ ```
904
+ - [ ] Support both old and new github_pages configuration
905
+ ```ruby
906
+ # v1 style (deprecated, still works)
907
+ target :production do
908
+ github_pages true
909
+ ping "https://example.com"
910
+ end
911
+
912
+ # v2 style (preferred)
913
+ target :production do
914
+ github_pages "https://example.com"
915
+ end
916
+ ```
917
+ - [ ] Add deprecation warnings that guide users to v2 API
918
+ - [ ] Update CHANGELOG with deprecation notices
919
+ - [ ] Release v1.9.0 with dual API support
920
+
921
+ **Success criteria:**
922
+ - All existing projects work without changes
923
+ - Deprecation warnings guide users to new API
924
+ - v2 API is fully functional alongside v1 API
925
+
926
+ ---
927
+
928
+ ### Phase 8: v2.0.0 Release
929
+ **Goal:** Release v2.0.0 with v1 API removed
930
+
931
+ - [ ] Remove v1 API compatibility code
932
+ - [ ] Remove `server` alias (breaking change)
933
+ - [ ] Remove old-style SSH configuration support
934
+ - [ ] Remove old-style strategy configuration
935
+ - [ ] Turn deprecation warnings into errors (if v1 API used)
936
+ - [ ] Update CHANGELOG with all breaking changes
937
+ - [ ] Ensure all tests pass
938
+ - [ ] Release v2.0.0
939
+
940
+ **Success criteria:**
941
+ - Only v2 API supported
942
+ - All tests pass
943
+ - Documentation is up to date
944
+ - CHANGELOG documents all changes
945
+
946
+ ---
947
+
948
+ ## Success Metrics
949
+
950
+ - [ ] Crucible successfully uses Jets deployment strategy
951
+ - [ ] Existing projects work with minimal bard.rb changes
952
+ - [ ] Documentation is clear and comprehensive
953
+ - [ ] Custom strategies can be created without modifying gem
954
+ - [ ] All tests pass
955
+ - [ ] No regressions in existing functionality
956
+ - [ ] Clear error messages when capabilities missing
957
+ - [ ] Default targets work as expected and can be overridden