kdeploy 1.1.9 → 1.2.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.
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
1
  # Kdeploy
2
+
2
3
  ```
3
4
  _ _
4
5
  /\ /\__| | ___ _ __ | | ___ _ _
@@ -9,29 +10,72 @@
9
10
 
10
11
  ⚡ Lightweight Agentless Deployment Tool
11
12
  🚀 Deploy with confidence, scale with ease
12
-
13
13
  ```
14
14
 
15
- A lightweight agentless deployment automation tool written in Ruby.
15
+ A lightweight, agentless deployment automation tool written in Ruby. Kdeploy enables you to deploy applications, manage configurations, and execute tasks across multiple servers using SSH, without requiring any agents or daemons on target machines.
16
16
 
17
17
  [![Gem Version](https://img.shields.io/gem/v/kdeploy)](https://rubygems.org/gems/kdeploy)
18
18
  [![Ruby](https://github.com/kevin197011/kdeploy/actions/workflows/gem-push.yml/badge.svg)](https://github.com/kevin197011/kdeploy/actions/workflows/gem-push.yml)
19
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
20
+
21
+ ## Table of Contents
22
+
23
+ - [Features](#-features)
24
+ - [Installation](#-installation)
25
+ - [Quick Start](#-quick-start)
26
+ - [Usage Guide](#-usage-guide)
27
+ - [Configuration](#-configuration)
28
+ - [Advanced Usage](#-advanced-usage)
29
+ - [Error Handling](#-error-handling)
30
+ - [Best Practices](#-best-practices)
31
+ - [Troubleshooting](#-troubleshooting)
32
+ - [Architecture](#-architecture)
33
+ - [Development](#-development)
34
+ - [Contributing](#-contributing)
35
+ - [License](#-license)
19
36
 
20
37
  ## 🌟 Features
21
38
 
22
- - 🔑 **Agentless Remote Deployment**: Uses SSH for secure remote execution
23
- - 📝 **Elegant Ruby DSL**: Simple and expressive task definition
24
- - 🚀 **Concurrent Execution**: Efficient parallel task processing
25
- - 📤 **File Upload Support**: Easy file and template deployment
26
- - 📊 **Task Status Tracking**: Real-time execution monitoring
27
- - 🔄 **ERB Template Support**: Dynamic configuration generation
28
- - 🎯 **Role-based Deployment**: Target specific server roles
29
- - 🔍 **Dry Run Mode**: Preview tasks before execution
30
- - 🎨 **Color-coded Output**: Green for success, Red for errors, Yellow for warnings
39
+ ### Core Features
40
+
41
+ - 🔑 **Agentless Remote Deployment**: Uses SSH for secure remote execution, no agents required
42
+ - 📝 **Elegant Ruby DSL**: Simple and expressive task definition syntax
43
+ - 🚀 **Concurrent Execution**: Efficient parallel task processing across multiple hosts
44
+ - 📤 **File Upload Support**: Easy file and template deployment via SCP
45
+ - 📊 **Task Status Tracking**: Real-time execution monitoring with detailed output
46
+ - 🔄 **ERB Template Support**: Dynamic configuration generation with variable substitution
47
+ - 🎯 **Role-based Deployment**: Target specific server roles for organized deployments
48
+ - 🔍 **Dry Run Mode**: Preview tasks before execution without making changes
49
+ - 🎨 **Color-coded Output**: Intuitive color scheme (Green: success, Red: errors, Yellow: warnings)
50
+ - ⚙️ **Flexible Host Targeting**: Execute tasks on specific hosts, roles, or all hosts
51
+ - 🔐 **Multiple Authentication Methods**: Support for SSH keys and password authentication
52
+ - 📈 **Execution Time Tracking**: Monitor task execution duration for performance analysis
53
+
54
+ ### Technical Features
55
+
56
+ - **Thread-safe Execution**: Built on `concurrent-ruby` for reliable parallel processing
57
+ - **Custom Error Handling**: Detailed error types for better debugging
58
+ - **Configuration Management**: Centralized configuration with sensible defaults
59
+ - **Extensible Architecture**: Modular design for easy extension
60
+ - **Shell Completion**: Auto-completion support for Bash and Zsh
31
61
 
32
62
  ## 📦 Installation
33
63
 
34
- Add this line to your application's Gemfile:
64
+ ### Requirements
65
+
66
+ - Ruby >= 2.7.0
67
+ - SSH access to target servers
68
+ - SSH keys or password authentication configured
69
+
70
+ ### Install via RubyGems
71
+
72
+ ```bash
73
+ gem install kdeploy
74
+ ```
75
+
76
+ ### Install via Bundler
77
+
78
+ Add this line to your application's `Gemfile`:
35
79
 
36
80
  ```ruby
37
81
  gem 'kdeploy'
@@ -43,22 +87,24 @@ And then execute:
43
87
  bundle install
44
88
  ```
45
89
 
46
- Or install it yourself as:
90
+ ### Verify Installation
47
91
 
48
92
  ```bash
49
- gem install kdeploy
93
+ kdeploy version
50
94
  ```
51
95
 
96
+ You should see the version information and banner.
97
+
52
98
  ### Shell Completion
53
99
 
54
- To enable command completion, add the following to your shell config:
100
+ Kdeploy automatically configures shell completion during installation. If needed, manually add to your shell config:
55
101
 
56
- For Bash (`~/.bashrc`):
102
+ **For Bash** (`~/.bashrc`):
57
103
  ```bash
58
104
  source "$(gem contents kdeploy | grep kdeploy.bash)"
59
105
  ```
60
106
 
61
- For Zsh (`~/.zshrc`):
107
+ **For Zsh** (`~/.zshrc`):
62
108
  ```bash
63
109
  source "$(gem contents kdeploy | grep kdeploy.zsh)"
64
110
  autoload -Uz compinit && compinit
@@ -75,17 +121,22 @@ Now you can use Tab completion for:
75
121
 
76
122
  ## 🚀 Quick Start
77
123
 
78
- 1. Initialize a new project:
124
+ ### 1. Initialize a New Project
79
125
 
80
126
  ```bash
81
127
  kdeploy init my-deployment
82
128
  ```
83
129
 
84
- 2. Edit the deployment configuration:
130
+ This creates a new directory with:
131
+ - `deploy.rb` - Main deployment configuration file
132
+ - `config/` - Directory for configuration files and templates
133
+ - `README.md` - Project documentation
85
134
 
86
- ```ruby
87
- # deploy.rb
135
+ ### 2. Configure Hosts and Tasks
136
+
137
+ Edit `deploy.rb`:
88
138
 
139
+ ```ruby
89
140
  # Define hosts
90
141
  host "web01", user: "ubuntu", ip: "10.0.0.1", key: "~/.ssh/id_rsa"
91
142
  host "web02", user: "ubuntu", ip: "10.0.0.2", key: "~/.ssh/id_rsa"
@@ -93,160 +144,886 @@ host "web02", user: "ubuntu", ip: "10.0.0.2", key: "~/.ssh/id_rsa"
93
144
  # Define roles
94
145
  role :web, %w[web01 web02]
95
146
 
96
- # Define tasks
97
- # 推荐多行命令用 heredoc(run <<~SHELL)
147
+ # Define deployment task
98
148
  task :deploy, roles: :web do
99
149
  run <<~SHELL
100
150
  sudo systemctl stop nginx
101
- echo "Deploying..."
102
- sudo systemctl start nginx
151
+ echo "Deploying application..."
103
152
  SHELL
153
+
104
154
  upload_template "./config/nginx.conf.erb", "/etc/nginx/nginx.conf",
105
155
  domain_name: "example.com",
106
156
  port: 3000
157
+
158
+ run "sudo systemctl start nginx"
107
159
  end
108
160
  ```
109
161
 
110
- 3. Run the deployment:
162
+ ### 3. Run Deployment
111
163
 
112
164
  ```bash
113
- kdeploy execute deploy.rb
165
+ kdeploy execute deploy.rb deploy
114
166
  ```
115
167
 
116
- 4. Demo:
168
+ ## 📖 Usage Guide
169
+
170
+ ### Command Reference
171
+
172
+ #### `kdeploy init [DIR]`
173
+
174
+ Initialize a new deployment project.
117
175
 
118
176
  ```bash
119
- https://github.com/kevin197011/kdeploy-app
177
+ # Initialize in current directory
178
+ kdeploy init .
179
+
180
+ # Initialize in named directory
181
+ kdeploy init my-deployment
120
182
  ```
121
183
 
122
- ## 📖 Usage Guide
184
+ #### `kdeploy execute TASK_FILE [TASK]`
123
185
 
124
- ### Task Execution
186
+ Execute deployment tasks from a configuration file.
125
187
 
188
+ **Basic Usage:**
126
189
  ```bash
127
190
  # Execute all tasks in the file
128
191
  kdeploy execute deploy.rb
129
192
 
130
193
  # Execute a specific task
131
194
  kdeploy execute deploy.rb deploy_web
195
+ ```
196
+
197
+ **Options:**
198
+ - `--limit HOSTS`: Limit execution to specific hosts (comma-separated)
199
+ - `--parallel NUM`: Number of parallel executions (default: 10)
200
+ - `--dry-run`: Preview mode - show what would be done without executing
201
+
202
+ **Examples:**
203
+ ```bash
204
+ # Preview deployment without executing
205
+ kdeploy execute deploy.rb deploy_web --dry-run
206
+
207
+ # Execute on specific hosts only
208
+ kdeploy execute deploy.rb deploy_web --limit web01,web02
132
209
 
133
- # Execute with dry run (preview mode)
134
- kdeploy execute deploy.rb --dry-run
210
+ # Use custom parallel count
211
+ kdeploy execute deploy.rb deploy_web --parallel 5
135
212
 
136
- # Execute on specific hosts
137
- kdeploy execute deploy.rb --limit web01,web02
213
+ # Combine options
214
+ kdeploy execute deploy.rb deploy_web --limit web01 --parallel 3 --dry-run
215
+ ```
216
+
217
+ #### `kdeploy version`
218
+
219
+ Show version information.
220
+
221
+ ```bash
222
+ kdeploy version
223
+ ```
224
+
225
+ #### `kdeploy help [COMMAND]`
226
+
227
+ Show help information.
228
+
229
+ ```bash
230
+ # Show general help
231
+ kdeploy help
138
232
 
139
- # Execute with custom parallel count (default: 10)
140
- kdeploy execute deploy.rb --parallel 10
233
+ # Show help for specific command
234
+ kdeploy help execute
141
235
  ```
142
236
 
143
237
  ### Host Definition
144
238
 
239
+ #### Basic Host Configuration
240
+
145
241
  ```ruby
146
- # Single host
242
+ # Single host with SSH key
147
243
  host "web01",
148
244
  user: "ubuntu",
149
245
  ip: "10.0.0.1",
150
246
  key: "~/.ssh/id_rsa"
151
247
 
152
- # Multiple hosts
248
+ # Host with password authentication
249
+ host "web02",
250
+ user: "admin",
251
+ ip: "10.0.0.2",
252
+ password: "your-password"
253
+
254
+ # Host with custom SSH port
255
+ host "web03",
256
+ user: "ubuntu",
257
+ ip: "10.0.0.3",
258
+ key: "~/.ssh/id_rsa",
259
+ port: 2222
260
+ ```
261
+
262
+ #### Host Configuration Options
263
+
264
+ | Option | Type | Required | Description |
265
+ |--------|------|----------|-------------|
266
+ | `user` | String | Yes | SSH username |
267
+ | `ip` | String | Yes | Server IP address or hostname |
268
+ | `key` | String | No* | Path to SSH private key file |
269
+ | `password` | String | No* | SSH password |
270
+ | `port` | Integer | No | SSH port (default: 22) |
271
+
272
+ \* Either `key` or `password` is required for authentication.
273
+
274
+ #### Dynamic Host Definition
275
+
276
+ ```ruby
277
+ # Define multiple hosts programmatically
153
278
  %w[web01 web02 web03].each do |name|
154
279
  host name,
155
280
  user: "ubuntu",
156
281
  ip: "10.0.0.#{name[-1]}",
157
282
  key: "~/.ssh/id_rsa"
158
283
  end
284
+
285
+ # Define hosts from external source
286
+ require 'yaml'
287
+ hosts_config = YAML.load_file('hosts.yml')
288
+ hosts_config.each do |name, config|
289
+ host name, **config
290
+ end
159
291
  ```
160
292
 
161
293
  ### Role Management
162
294
 
295
+ Roles allow you to group hosts and target them collectively in tasks.
296
+
163
297
  ```ruby
164
298
  # Define roles
165
- role :web, %w[web01 web02]
299
+ role :web, %w[web01 web02 web03]
166
300
  role :db, %w[db01 db02]
167
- role :all, %w[web01 web02 db01 db02]
301
+ role :cache, %w[cache01]
302
+ role :all, %w[web01 web02 web03 db01 db02 cache01]
168
303
 
169
304
  # Use roles in tasks
170
305
  task :deploy_web, roles: :web do
171
- # Tasks for web servers
306
+ # Executes on all web servers
172
307
  end
173
308
 
174
309
  task :backup_db, roles: :db do
175
- # Tasks for database servers
310
+ # Executes on all database servers
311
+ end
312
+
313
+ # Multiple roles
314
+ task :deploy_all, roles: [:web, :cache] do
315
+ # Executes on web and cache servers
176
316
  end
177
317
  ```
178
318
 
179
319
  ### Task Definition
180
320
 
321
+ #### Basic Task
322
+
181
323
  ```ruby
182
- # Basic task
183
- task :simple do
324
+ task :hello do
184
325
  run "echo 'Hello, World!'"
185
326
  end
327
+ ```
186
328
 
187
- # Role-based task
188
- task :deploy, roles: :web do
329
+ #### Role-based Task
330
+
331
+ ```ruby
332
+ task :deploy_web, roles: :web do
333
+ run "sudo systemctl restart nginx"
334
+ end
335
+ ```
336
+
337
+ #### Host-specific Task
338
+
339
+ ```ruby
340
+ task :maintenance, on: %w[web01] do
189
341
  run <<~SHELL
190
342
  sudo systemctl stop nginx
343
+ sudo apt-get update && sudo apt-get upgrade -y
191
344
  sudo systemctl start nginx
192
345
  SHELL
193
- upload "./config/nginx.conf", "/etc/nginx/nginx.conf"
194
346
  end
347
+ ```
195
348
 
196
- # Host-specific task
197
- task :maintenance, on: %w[web01] do
198
- run <<~SHELL
199
- sudo apt-get update
200
- sudo apt-get upgrade -y
201
- SHELL
349
+ #### Task with Multiple Commands
350
+
351
+ ```ruby
352
+ task :deploy, roles: :web do
353
+ # Stop service
354
+ run "sudo systemctl stop nginx"
355
+
356
+ # Upload configuration
357
+ upload "./config/nginx.conf", "/etc/nginx/nginx.conf"
358
+
359
+ # Start service
360
+ run "sudo systemctl start nginx"
361
+
362
+ # Verify status
363
+ run "sudo systemctl status nginx"
202
364
  end
203
365
  ```
204
366
 
367
+ #### Task Options
368
+
369
+ | Option | Type | Description |
370
+ |-------|------|-------------|
371
+ | `roles` | Symbol/Array | Execute on hosts with specified role(s) |
372
+ | `on` | Array | Execute on specific host(s) |
373
+
374
+ **Note**: If neither `roles` nor `on` is specified, the task executes on all defined hosts.
375
+
376
+ ### Command Types
377
+
378
+ #### `run` - Execute Shell Commands
379
+
380
+ Execute commands on remote servers.
381
+
382
+ ```ruby
383
+ # Single line command
384
+ run "sudo systemctl restart nginx"
385
+
386
+ # Multi-line command (recommended for complex commands)
387
+ run <<~SHELL
388
+ cd /var/www/app
389
+ git pull origin main
390
+ bundle install
391
+ sudo systemctl restart puma
392
+ SHELL
393
+ ```
394
+
395
+ **Best Practice**: Use heredoc (`<<~SHELL`) for multi-line commands to improve readability.
396
+
397
+ #### `upload` - Upload Files
398
+
399
+ Upload files to remote servers.
400
+
401
+ ```ruby
402
+ upload "./config/nginx.conf", "/etc/nginx/nginx.conf"
403
+ upload "./scripts/deploy.sh", "/tmp/deploy.sh"
404
+ ```
405
+
406
+ **Parameters:**
407
+ - `source`: Local file path
408
+ - `destination`: Remote file path
409
+
410
+ #### `upload_template` - Upload ERB Templates
411
+
412
+ Upload and render ERB templates with variable substitution.
413
+
414
+ ```ruby
415
+ upload_template "./config/nginx.conf.erb", "/etc/nginx/nginx.conf",
416
+ domain_name: "example.com",
417
+ port: 3000,
418
+ worker_processes: 4
419
+ ```
420
+
421
+ **Parameters:**
422
+ - `source`: Local ERB template file path
423
+ - `destination`: Remote file path
424
+ - `variables`: Hash of variables for template rendering
425
+
205
426
  ### Template Support
206
427
 
207
- Create an ERB template (`config/nginx.conf.erb`):
428
+ Kdeploy supports ERB (Embedded Ruby) templates for dynamic configuration generation.
429
+
430
+ #### Creating Templates
431
+
432
+ Create an ERB template file (e.g., `config/nginx.conf.erb`):
208
433
 
209
434
  ```erb
210
- server {
211
- listen 80;
212
- server_name <%= domain_name %>;
213
-
214
- location / {
215
- proxy_pass http://localhost:<%= port %>;
216
- proxy_set_header Host $host;
217
- proxy_set_header X-Real-IP $remote_addr;
435
+ user nginx;
436
+ worker_processes <%= worker_processes %>;
437
+ error_log /var/log/nginx/error.log;
438
+ pid /run/nginx.pid;
439
+
440
+ events {
441
+ worker_connections <%= worker_connections %>;
442
+ }
443
+
444
+ http {
445
+ include /etc/nginx/mime.types;
446
+ default_type application/octet-stream;
447
+
448
+ upstream app_servers {
449
+ server 127.0.0.1:<%= port %>;
450
+ }
451
+
452
+ server {
453
+ listen 80;
454
+ server_name <%= domain_name %>;
455
+
456
+ location / {
457
+ proxy_pass http://app_servers;
458
+ proxy_http_version 1.1;
459
+ proxy_set_header Upgrade $http_upgrade;
460
+ proxy_set_header Connection 'upgrade';
461
+ proxy_set_header Host $host;
462
+ proxy_cache_bypass $http_upgrade;
463
+ }
218
464
  }
219
465
  }
220
466
  ```
221
467
 
222
- Use the template in your task:
468
+ #### Using Templates
223
469
 
224
470
  ```ruby
225
471
  task :deploy_config do
226
- upload_template "./config/nginx.conf.erb", "/etc/nginx/sites-available/myapp.conf",
472
+ upload_template "./config/nginx.conf.erb", "/etc/nginx/nginx.conf",
227
473
  domain_name: "example.com",
228
- port: 3000
474
+ port: 3000,
475
+ worker_processes: 4,
476
+ worker_connections: 2048
477
+ end
478
+ ```
479
+
480
+ #### Template Features
481
+
482
+ - Full ERB syntax support
483
+ - Variable substitution
484
+ - Conditional logic
485
+ - Loops and iterations
486
+ - Ruby code execution
487
+
488
+ ### Inventory Block
489
+
490
+ Use the `inventory` block to organize host definitions:
491
+
492
+ ```ruby
493
+ inventory do
494
+ host 'web01', user: 'ubuntu', ip: '10.0.0.1', key: '~/.ssh/id_rsa'
495
+ host 'web02', user: 'ubuntu', ip: '10.0.0.2', key: '~/.ssh/id_rsa'
496
+ host 'db01', user: 'root', ip: '10.0.0.3', key: '~/.ssh/id_rsa'
497
+ end
498
+ ```
499
+
500
+ ## ⚙️ Configuration
501
+
502
+ ### Default Configuration
503
+
504
+ Kdeploy uses sensible defaults that can be customized:
505
+
506
+ - **Default Parallel Count**: 10 concurrent executions
507
+ - **SSH Timeout**: 30 seconds
508
+ - **Host Key Verification**: Disabled (for convenience, enable in production)
509
+
510
+ ### Environment Variables
511
+
512
+ You can override defaults using environment variables:
513
+
514
+ ```bash
515
+ export KDEPLOY_PARALLEL=5
516
+ export KDEPLOY_SSH_TIMEOUT=60
517
+ ```
518
+
519
+ ### Configuration File
520
+
521
+ For project-specific configuration, create a `.kdeploy.yml`:
522
+
523
+ ```yaml
524
+ parallel: 5
525
+ ssh_timeout: 60
526
+ verify_host_key: true
527
+ ```
528
+
529
+ ## 🔧 Advanced Usage
530
+
531
+ ### Conditional Execution
532
+
533
+ Use Ruby conditionals in your deployment files:
534
+
535
+ ```ruby
536
+ task :deploy do
537
+ if ENV['ENVIRONMENT'] == 'production'
538
+ run "sudo systemctl stop nginx"
539
+ end
540
+
541
+ upload "./config/nginx.conf", "/etc/nginx/nginx.conf"
542
+
543
+ if ENV['ENVIRONMENT'] == 'production'
544
+ run "sudo systemctl start nginx"
545
+ end
546
+ end
547
+ ```
548
+
549
+ ### Looping Over Hosts
550
+
551
+ ```ruby
552
+ # Execute different commands based on host
553
+ task :custom_setup do
554
+ @hosts.each do |name, config|
555
+ if name.start_with?('web')
556
+ run "echo 'Web server: #{name}'"
557
+ elsif name.start_with?('db')
558
+ run "echo 'Database server: #{name}'"
559
+ end
560
+ end
561
+ end
562
+ ```
563
+
564
+ ### Error Handling in Tasks
565
+
566
+ ```ruby
567
+ task :deploy do
568
+ run "sudo systemctl stop nginx" || raise "Failed to stop nginx"
569
+ upload "./config/nginx.conf", "/etc/nginx/nginx.conf"
570
+ run "sudo systemctl start nginx" || raise "Failed to start nginx"
571
+ end
572
+ ```
573
+
574
+ ### Using External Libraries
575
+
576
+ ```ruby
577
+ require 'yaml'
578
+ require 'json'
579
+
580
+ # Load configuration from external files
581
+ config = YAML.load_file('config.yml')
582
+
583
+ task :deploy do
584
+ config['commands'].each do |cmd|
585
+ run cmd
586
+ end
229
587
  end
230
588
  ```
231
589
 
590
+ ### Task Dependencies
591
+
592
+ While Kdeploy doesn't have built-in task dependencies, you can achieve this with Ruby:
593
+
594
+ ```ruby
595
+ task :setup do
596
+ run "echo 'Setting up...'"
597
+ end
598
+
599
+ task :deploy do
600
+ # Manually call setup task
601
+ self.class.kdeploy_tasks[:setup][:block].call.each do |cmd|
602
+ case cmd[:type]
603
+ when :run
604
+ run cmd[:command]
605
+ when :upload
606
+ upload cmd[:source], cmd[:destination]
607
+ end
608
+ end
609
+
610
+ run "echo 'Deploying...'"
611
+ end
612
+ ```
613
+
614
+ ## 🚨 Error Handling
615
+
616
+ ### Error Types
617
+
618
+ Kdeploy provides specific error types for better debugging:
619
+
620
+ - `Kdeploy::TaskNotFoundError` - Task not found
621
+ - `Kdeploy::HostNotFoundError` - Host not found
622
+ - `Kdeploy::SSHError` - SSH operation failed
623
+ - `Kdeploy::SCPError` - SCP upload failed
624
+ - `Kdeploy::TemplateError` - Template rendering failed
625
+ - `Kdeploy::ConfigurationError` - Configuration error
626
+ - `Kdeploy::FileNotFoundError` - File not found
627
+
628
+ ### Error Output
629
+
630
+ Errors are displayed with:
631
+ - Red color coding
632
+ - Detailed error messages
633
+ - Host information
634
+ - Original error context
635
+
636
+ ### Handling Errors
637
+
638
+ ```ruby
639
+ # In your deployment file
640
+ begin
641
+ task :deploy do
642
+ run "risky-command"
643
+ end
644
+ rescue Kdeploy::SSHError => e
645
+ puts "SSH Error: #{e.message}"
646
+ # Handle error
647
+ end
648
+ ```
649
+
650
+ ## 💡 Best Practices
651
+
652
+ ### 1. Use Heredoc for Multi-line Commands
653
+
654
+ ```ruby
655
+ # ✅ Good
656
+ run <<~SHELL
657
+ cd /var/www/app
658
+ git pull origin main
659
+ bundle install
660
+ SHELL
661
+
662
+ # ❌ Avoid
663
+ run "cd /var/www/app && git pull origin main && bundle install"
664
+ ```
665
+
666
+ ### 2. Organize with Roles
667
+
668
+ ```ruby
669
+ # ✅ Good - Use roles for organization
670
+ role :web, %w[web01 web02]
671
+ role :db, %w[db01 db02]
672
+
673
+ task :deploy_web, roles: :web do
674
+ # ...
675
+ end
676
+
677
+ # ❌ Avoid - Hardcoding host names
678
+ task :deploy do
679
+ # Hard to maintain
680
+ end
681
+ ```
682
+
683
+ ### 3. Use Templates for Dynamic Configuration
684
+
685
+ ```ruby
686
+ # ✅ Good - Use templates
687
+ upload_template "./config/nginx.conf.erb", "/etc/nginx/nginx.conf",
688
+ domain_name: "example.com",
689
+ port: 3000
690
+
691
+ # ❌ Avoid - Hardcoding values
692
+ run "echo 'server_name example.com;' > /etc/nginx/nginx.conf"
693
+ ```
694
+
695
+ ### 4. Validate Before Deployment
696
+
697
+ ```ruby
698
+ task :deploy do
699
+ # Validate configuration
700
+ run "nginx -t" || raise "Nginx configuration is invalid"
701
+
702
+ # Deploy
703
+ upload "./config/nginx.conf", "/etc/nginx/nginx.conf"
704
+ run "sudo systemctl reload nginx"
705
+ end
706
+ ```
707
+
708
+ ### 5. Use Dry Run for Testing
709
+
710
+ Always test with `--dry-run` before actual deployment:
711
+
712
+ ```bash
713
+ kdeploy execute deploy.rb deploy_web --dry-run
714
+ ```
715
+
716
+ ### 6. Organize Files Properly
717
+
718
+ ```
719
+ project/
720
+ ├── deploy.rb # Main deployment file
721
+ ├── config/ # Configuration files
722
+ │ ├── nginx.conf.erb # Templates
723
+ │ └── app.conf # Static configs
724
+ └── scripts/ # Helper scripts
725
+ └── deploy.sh
726
+ ```
727
+
728
+ ### 7. Version Control
729
+
730
+ - Commit `deploy.rb` and templates
731
+ - Use `.gitignore` for sensitive files
732
+ - Store secrets in environment variables
733
+
734
+ ### 8. Parallel Execution
735
+
736
+ Adjust parallel count based on your infrastructure:
737
+
738
+ ```bash
739
+ # For many hosts, increase parallel count
740
+ kdeploy execute deploy.rb deploy --parallel 20
741
+
742
+ # For limited resources, decrease
743
+ kdeploy execute deploy.rb deploy --parallel 3
744
+ ```
745
+
746
+ ## 🔍 Troubleshooting
747
+
748
+ ### Common Issues
749
+
750
+ #### SSH Authentication Failed
751
+
752
+ **Problem**: `SSH authentication failed`
753
+
754
+ **Solutions**:
755
+ 1. Verify SSH key path is correct
756
+ 2. Check key permissions: `chmod 600 ~/.ssh/id_rsa`
757
+ 3. Test SSH connection manually: `ssh user@host`
758
+ 4. Verify username and IP address
759
+
760
+ #### Host Not Found
761
+
762
+ **Problem**: `No hosts found for task`
763
+
764
+ **Solutions**:
765
+ 1. Verify host names in task match defined hosts
766
+ 2. Check role definitions
767
+ 3. Verify `--limit` option if used
768
+
769
+ #### Command Execution Failed
770
+
771
+ **Problem**: Commands fail on remote server
772
+
773
+ **Solutions**:
774
+ 1. Test commands manually on target server
775
+ 2. Check user permissions (may need sudo)
776
+ 3. Verify command syntax
777
+ 4. Check server logs
778
+
779
+ #### Template Rendering Error
780
+
781
+ **Problem**: Template upload fails
782
+
783
+ **Solutions**:
784
+ 1. Verify ERB syntax in template
785
+ 2. Check all required variables are provided
786
+ 3. Validate template file exists
787
+ 4. Test template rendering locally
788
+
789
+ #### Connection Timeout
790
+
791
+ **Problem**: SSH connection times out
792
+
793
+ **Solutions**:
794
+ 1. Check network connectivity
795
+ 2. Verify firewall rules
796
+ 3. Increase timeout in configuration
797
+ 4. Check SSH service on target server
798
+
799
+ ### Debug Mode
800
+
801
+ Enable verbose output by checking the execution output. Kdeploy provides detailed information about:
802
+ - Task execution status
803
+ - Command output
804
+ - Error messages
805
+ - Execution duration
806
+
807
+ ### Getting Help
808
+
809
+ - Check [GitHub Issues](https://github.com/kevin197011/kdeploy/issues)
810
+ - Review example projects
811
+ - Read the documentation
812
+ - Ask in discussions
813
+
814
+ ## 🏗️ Architecture
815
+
816
+ ### Core Components
817
+
818
+ - **CLI** (`cli.rb`): Command-line interface using Thor
819
+ - **DSL** (`dsl.rb`): Domain-specific language for task definition
820
+ - **Executor** (`executor.rb`): SSH/SCP execution engine
821
+ - **Runner** (`runner.rb`): Concurrent task execution coordinator
822
+ - **CommandExecutor** (`command_executor.rb`): Individual command execution
823
+ - **CommandGrouper** (`command_grouper.rb`): Command grouping logic
824
+ - **Template** (`template.rb`): ERB template rendering
825
+ - **Output** (`output.rb`): Output formatting and display
826
+ - **Configuration** (`configuration.rb`): Configuration management
827
+ - **Errors** (`errors.rb`): Custom error types
828
+
829
+ ### Execution Flow
830
+
831
+ 1. **Parse Configuration**: Load and parse `deploy.rb`
832
+ 2. **Resolve Hosts**: Determine target hosts based on task definition
833
+ 3. **Group Commands**: Group commands by type for efficient execution
834
+ 4. **Execute Concurrently**: Run tasks in parallel across hosts
835
+ 5. **Collect Results**: Gather execution results and status
836
+ 6. **Display Output**: Format and display results to user
837
+
838
+ ### Concurrency Model
839
+
840
+ Kdeploy uses `concurrent-ruby` with a fixed thread pool:
841
+ - Default: 10 concurrent executions
842
+ - Configurable via `--parallel` option
843
+ - Thread-safe result collection
844
+ - Automatic resource cleanup
845
+
232
846
  ## 🔧 Development
233
847
 
234
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
848
+ ### Setup Development Environment
849
+
850
+ ```bash
851
+ # Clone repository
852
+ git clone https://github.com/kevin197011/kdeploy.git
853
+ cd kdeploy
854
+
855
+ # Install dependencies
856
+ bundle install
857
+
858
+ # Run tests
859
+ bundle exec rspec
860
+
861
+ # Run console
862
+ bin/console
863
+ ```
864
+
865
+ ### Project Structure
235
866
 
236
- To install this gem onto your local machine, run `bundle exec rake install`.
867
+ ```
868
+ kdeploy/
869
+ ├── lib/
870
+ │ └── kdeploy/
871
+ │ ├── cli.rb # CLI interface
872
+ │ ├── dsl.rb # DSL definition
873
+ │ ├── executor.rb # SSH/SCP executor
874
+ │ ├── runner.rb # Task runner
875
+ │ ├── command_executor.rb # Command executor
876
+ │ ├── command_grouper.rb # Command grouper
877
+ │ ├── template.rb # Template handler
878
+ │ ├── output.rb # Output interface
879
+ │ ├── configuration.rb # Configuration
880
+ │ ├── errors.rb # Error types
881
+ │ └── ...
882
+ ├── spec/ # Tests
883
+ ├── exe/ # Executables
884
+ ├── sample/ # Example projects
885
+ └── README.md # This file
886
+ ```
887
+
888
+ ### Running Tests
889
+
890
+ ```bash
891
+ # Run all tests
892
+ bundle exec rspec
893
+
894
+ # Run specific test file
895
+ bundle exec rspec spec/kdeploy_spec.rb
896
+
897
+ # Run with coverage
898
+ COVERAGE=true bundle exec rspec
899
+ ```
900
+
901
+ ### Building the Gem
902
+
903
+ ```bash
904
+ # Build gem
905
+ gem build kdeploy.gemspec
906
+
907
+ # Install locally
908
+ gem install ./kdeploy-*.gem
909
+ ```
910
+
911
+ ### Code Style
912
+
913
+ The project uses RuboCop for code style:
914
+
915
+ ```bash
916
+ # Check style
917
+ bundle exec rubocop
918
+
919
+ # Auto-fix issues
920
+ bundle exec rubocop -a
921
+ ```
237
922
 
238
923
  ## 🤝 Contributing
239
924
 
240
- 1. Fork it
241
- 2. Create your feature branch (`git checkout -b feature/my-new-feature`)
242
- 3. Commit your changes (`git commit -am 'Add some feature'`)
243
- 4. Push to the branch (`git push origin feature/my-new-feature`)
244
- 5. Create a new Pull Request
925
+ Contributions are welcome! Please follow these steps:
926
+
927
+ 1. **Fork the repository**
928
+ 2. **Create a feature branch**: `git checkout -b feature/my-new-feature`
929
+ 3. **Make your changes**: Follow the code style and add tests
930
+ 4. **Commit your changes**: Use conventional commit messages
931
+ 5. **Push to the branch**: `git push origin feature/my-new-feature`
932
+ 6. **Create a Pull Request**: Provide a clear description of changes
933
+
934
+ ### Contribution Guidelines
935
+
936
+ - Follow existing code style
937
+ - Add tests for new features
938
+ - Update documentation
939
+ - Ensure all tests pass
940
+ - Follow conventional commit format
941
+
942
+ ### Commit Message Format
943
+
944
+ Follow [Conventional Commits](https://www.conventionalcommits.org/):
945
+
946
+ ```
947
+ <type>(<scope>): <subject>
948
+
949
+ <body>
950
+
951
+ <footer>
952
+ ```
953
+
954
+ Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`
955
+
956
+ ## 📚 Examples
957
+
958
+ ### Example Projects
959
+
960
+ Check out the [example project](https://github.com/kevin197011/kdeploy-app) for a complete deployment setup.
961
+
962
+ ### Common Deployment Scenarios
963
+
964
+ #### Web Application Deployment
965
+
966
+ ```ruby
967
+ host "web01", user: "deploy", ip: "10.0.0.1", key: "~/.ssh/id_rsa"
968
+ role :web, %w[web01]
969
+
970
+ task :deploy_app, roles: :web do
971
+ run <<~SHELL
972
+ cd /var/www/app
973
+ git pull origin main
974
+ bundle install
975
+ rake db:migrate
976
+ sudo systemctl restart puma
977
+ SHELL
978
+ end
979
+ ```
980
+
981
+ #### Database Backup
982
+
983
+ ```ruby
984
+ host "db01", user: "postgres", ip: "10.0.0.10", key: "~/.ssh/id_rsa"
985
+ role :db, %w[db01]
986
+
987
+ task :backup, roles: :db do
988
+ run <<~SHELL
989
+ pg_dump mydb > /tmp/backup_$(date +%Y%m%d).sql
990
+ gzip /tmp/backup_*.sql
991
+ aws s3 cp /tmp/backup_*.sql.gz s3://backups/
992
+ rm /tmp/backup_*.sql.gz
993
+ SHELL
994
+ end
995
+ ```
996
+
997
+ #### Configuration Management
998
+
999
+ ```ruby
1000
+ task :update_config, roles: :web do
1001
+ upload_template "./config/app.yml.erb", "/etc/app/config.yml",
1002
+ environment: "production",
1003
+ database_url: ENV['DATABASE_URL'],
1004
+ redis_url: ENV['REDIS_URL']
1005
+
1006
+ run "sudo systemctl reload app"
1007
+ end
1008
+ ```
245
1009
 
246
1010
  ## 📝 License
247
1011
 
248
1012
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
249
1013
 
250
- ## 🔍 Code of Conduct
1014
+ ## 🔗 Links
1015
+
1016
+ - **GitHub**: https://github.com/kevin197011/kdeploy
1017
+ - **RubyGems**: https://rubygems.org/gems/kdeploy
1018
+ - **Issues**: https://github.com/kevin197011/kdeploy/issues
1019
+ - **Example Project**: https://github.com/kevin197011/kdeploy-app
1020
+
1021
+ ## 🙏 Acknowledgments
1022
+
1023
+ - Built with [Thor](https://github.com/rails/thor) for CLI
1024
+ - Uses [net-ssh](https://github.com/net-ssh/net-ssh) for SSH operations
1025
+ - Powered by [concurrent-ruby](https://github.com/ruby-concurrency/concurrent-ruby) for concurrency
1026
+
1027
+ ---
251
1028
 
252
- Everyone interacting in the Kdeploy project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/kdeploy/blob/main/CODE_OF_CONDUCT.md).
1029
+ **Made with ❤️ for the DevOps community**