shipfe 1.0.2 → 1.1.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.
package/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Shipfe
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/shipfe.svg)](https://www.npmjs.com/package/shipfe)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![GitHub](https://img.shields.io/badge/GitHub-Master--Jian/shipfe--rust-blue.svg)](https://github.com/Master-Jian/shipfe-rust)
6
+
3
7
  A powerful, **free**, **Rust-based** deployment tool for web applications that **never requests network** and enables **one-click static frontend deployment** to servers. Supports multiple environments and sub-environments with zero-downtime atomic deployments.
4
8
 
5
9
  ## Key Features
@@ -13,6 +17,10 @@ A powerful, **free**, **Rust-based** deployment tool for web applications that *
13
17
  - 📦 **Sub-Environment Support**: Deploy multiple apps to the same server
14
18
  - 🔑 **Flexible Authentication**: SSH key, password, or environment variable authentication
15
19
  - 📝 **Detailed Logging**: Comprehensive deployment logs for troubleshooting
20
+ - 🗂️ **Shared Asset Management**: Deduplicate hashed static assets across releases
21
+ - 📊 **Resource Snapshot**: Generate deployment snapshots with file manifests
22
+ - 🧹 **Automatic Cleanup**: Configurable retention of old releases and unused assets
23
+ - 🗑️ **Shared Asset Reset**: Automatically clear all shared assets on deployment for clean state
16
24
 
17
25
  ## Installation
18
26
 
@@ -83,11 +91,14 @@ Edit `shipfe.config.json` to configure your deployment settings:
83
91
  "host": "dev.example.com",
84
92
  "port": 22,
85
93
  "username": "deploy",
86
- "remote_deploy_path": "/var/www/dev",
87
- "delete_old": false
94
+ "remote_deploy_path": "/var/www/dev"
88
95
  }
89
96
  ],
90
- "remote_tmp": "/tmp"
97
+ "remote_tmp": "/tmp",
98
+ "hashed_asset_patterns": ["assets/"],
99
+ "enable_shared": true,
100
+ "keep_releases": 5,
101
+ "delete_old": false
91
102
  }
92
103
  }
93
104
  }
@@ -115,27 +126,24 @@ Each server can have its own authentication method. Shipfe tries authentication
115
126
  "port": 22,
116
127
  "username": "deploy",
117
128
  "password": "web1_password",
118
- "remote_deploy_path": "/var/www/prod",
119
- "delete_old": false
129
+ "remote_deploy_path": "/var/www/prod"
120
130
  },
121
131
  {
122
132
  "host": "web2.prod.com",
123
133
  "port": 22,
124
134
  "username": "deploy",
125
135
  "key_path": "/home/user/.ssh/web2_key",
126
- "remote_deploy_path": "/var/www/prod",
127
- "delete_old": false
136
+ "remote_deploy_path": "/var/www/prod"
128
137
  },
129
138
  {
130
139
  "host": "web3.prod.com",
131
140
  "port": 22,
132
141
  "username": "deploy",
133
- "key_path": "/home/user/.ssh/web3_key",
134
- "remote_deploy_path": "/var/www/prod",
135
- "delete_old": false
142
+ "remote_deploy_path": "/var/www/prod"
136
143
  }
137
144
  ],
138
- "remote_tmp": "/tmp"
145
+ "remote_tmp": "/tmp",
146
+ "delete_old": false
139
147
  }
140
148
  }
141
149
  }
@@ -155,11 +163,14 @@ For deploying multiple applications or different configurations to the same serv
155
163
  "host": "dev.example.com",
156
164
  "port": 22,
157
165
  "username": "deploy",
158
- "remote_deploy_path": "/var/www/dev",
159
- "delete_old": false
166
+ "remote_deploy_path": "/var/www/dev"
160
167
  }
161
168
  ],
162
169
  "remote_tmp": "/tmp",
170
+ "hashed_asset_patterns": ["assets/"],
171
+ "enable_shared": true,
172
+ "keep_releases": 5,
173
+ "delete_old": false,
163
174
  "sub_environments": {
164
175
  "admin": {
165
176
  "build_command": "npm run build:admin",
@@ -189,14 +200,411 @@ shipfe deploy --profile dev-cu
189
200
  shipfe deploy --profile dev --all-sub
190
201
  ```
191
202
 
192
- ### Deploy all sub-environments at once
203
+ ### Configuration Details
204
+
205
+ Here are all available configuration options in `shipfe.config.json`:
206
+
207
+ #### Global Configuration Options
208
+
209
+ - **`enable_shared`** (boolean, default: false)
210
+ - Enable shared asset management
211
+ - When enabled, matching files are hashed and stored in a shared directory to avoid re-uploading duplicates
212
+ - Suitable for applications with frequent deployments and many static assets
213
+
214
+ - **`hashed_asset_patterns`** (array of strings, default: [])
215
+ - File patterns for assets that should be hashed and shared
216
+ - Supports glob patterns like `"**/*.js"`, `"**/*.css"`, `"**/*.{png,jpg,svg}"`
217
+ - Only matching files will be hashed and shared; others are uploaded fresh each deployment
218
+
219
+ - **`keep_releases`** (number, default: 10)
220
+ - Number of release versions to keep
221
+ - Older releases beyond this number will be automatically cleaned up
222
+ - Set to 0 to disable automatic cleanup
223
+
224
+ #### Environment Configuration Options
225
+
226
+ Each environment (like `dev`, `prod`) can contain these options:
227
+
228
+ - **`build_command`** (string, required)
229
+ - Local build command, e.g., `"npm run build"` or `"yarn build"`
230
+
231
+ - **`local_dist_path`** (string, required)
232
+ - Local build output directory path, e.g., `"./dist"` or `"./build"`
233
+
234
+ - **`servers`** (array of objects, required)
235
+ - List of servers, each containing:
236
+ - **`host`** (string, required): Server hostname or IP address
237
+ - **`port`** (number, default: 22): SSH port
238
+ - **`username`** (string, required): SSH username
239
+ - **`password`** (string, optional): SSH password (not recommended, use keys instead)
240
+ - **`key_path`** (string, optional): Path to SSH private key file
241
+ - **`remote_deploy_path`** (string, required): Deployment directory path on server
242
+
243
+ - **`remote_tmp`** (string, default: "/tmp")
244
+ - Temporary directory path on server for file uploads
245
+
246
+ - **`sub_environments`** (object, optional)
247
+ - Sub-environment configurations, keyed by sub-environment name
248
+ - Sub-environments inherit parent settings but can override `build_command`, `local_dist_path`, `remote_deploy_path`
249
+
250
+ - **`delete_old`** (boolean, default: false)
251
+ - Delete all old releases after each deployment
252
+ - Keep only the current deployment
253
+ - Overrides `keep_releases` setting
254
+
255
+ #### Shared Assets and Hashing Configuration Explained
256
+
257
+ **How Shared Assets Work:**
258
+
259
+ 1. **File Matching**: Files are matched against `hashed_asset_patterns`
260
+ 2. **Hash Calculation**: SHA256 hashes are computed for matching files
261
+ 3. **Storage Strategy**:
262
+ - Identical files are stored only once in the `shared/assets/` directory
263
+ - Filename format: `{hash}.{ext}`, e.g., `abc123def456.js`
264
+ 4. **Link Creation**: Hard links are created in release directories pointing to shared files
265
+ 5. **Cleanup**: Shared files no longer referenced by any kept release are removed
266
+
267
+ **Configuration Example with Explanations:**
268
+
269
+ ```json
270
+ {
271
+ "enable_shared": true,
272
+ "hashed_asset_patterns": [
273
+ "**/*.js", // Match all JS files
274
+ "**/*.css", // Match all CSS files
275
+ "**/*.{png,jpg}", // Match PNG and JPG files
276
+ "!**/vendor/**" // Exclude vendor directory (if not needed for sharing)
277
+ ],
278
+ "keep_releases": 5
279
+ }
280
+ ```
281
+
282
+ **When to Use:**
283
+ - **Enable sharing**: Large applications, frequent deployments, many static assets
284
+ - **Disable sharing**: Small applications, infrequent deployments, or need for simple debugging
285
+
286
+ **Important Notes:**
287
+ - Shared assets require filesystem support for hard links
288
+ - On first enable, all matching files will be hashed
289
+ - Disabling sharing doesn't remove existing shared files (manual cleanup required)
290
+
291
+ ### Shared Assets Management
292
+
293
+ Shipfe supports deduplication of hashed static assets across releases to save disk space and bandwidth. When `enable_shared` is set to `true`, hashed assets are stored in a shared directory and hard-linked in each release.
294
+
295
+ **Configuration:**
296
+ ```json
297
+ {
298
+ "environments": {
299
+ "prod": {
300
+ "enable_shared": true,
301
+ "hashed_asset_patterns": ["assets/"],
302
+ "keep_releases": 5,
303
+ "delete_old": false
304
+ }
305
+ }
306
+ }
307
+ ```
308
+
309
+ **How it works:**
310
+ 1. **Asset Detection**: Automatically detects hashed files based on:
311
+ - User-defined patterns (e.g., `["assets/", "static/"]`)
312
+ - Filename format: `name-hash.ext` (e.g., `app-abc123.js`, `style-def456.css`)
313
+
314
+ 2. **Deduplication Process**:
315
+ - First deployment: Copies hashed assets to `shared/assets/`
316
+ - Subsequent deployments: Creates hard links to existing shared assets
317
+ - Same hash = same file, no duplication
318
+
319
+ 3. **Shared Asset Reset**: At the start of each deployment, all existing assets in the `shared/` directory are cleared to ensure a clean state, then `shared/assets/` is recreated.
320
+
321
+ 4. **Automatic Cleanup**: Removes unused assets when no longer referenced by any kept release
322
+
323
+ **Benefits:**
324
+ - **Disk Space**: Saves storage by eliminating duplicate hashed files
325
+ - **Bandwidth**: Faster deployments with smaller transfer sizes
326
+ - **Performance**: Hard links provide instant access with minimal overhead
327
+
328
+ **Example Directory Structure:**
329
+ ```
330
+ remote_deploy_path/
331
+ ├── releases/
332
+ │ ├── 20260304_120000/
333
+ │ │ ├── index.html
334
+ │ │ └── assets/
335
+ │ │ ├── app.js -> ../../../shared/assets/app-abc123.js
336
+ │ │ └── style.css -> ../../../shared/assets/style-def456.css
337
+ │ └── 20260304_120100/
338
+ │ ├── index.html
339
+ │ └── assets/
340
+ │ ├── app.js -> ../../../shared/assets/app-abc123.js (same file)
341
+ │ └── style.css -> ../../../shared/assets/style-ghi789.css (new)
342
+ ├── shared/
343
+ │ └── assets/
344
+ │ ├── app-abc123.js
345
+ │ ├── style-def456.css
346
+ │ └── style-ghi789.css
347
+ └── current -> releases/20260304_120100
348
+ ```
349
+
350
+ ### Automatic Cleanup
351
+
352
+ Shipfe provides configurable automatic cleanup of old releases and unused shared assets to manage disk usage efficiently.
353
+
354
+ **Configuration Options:**
355
+
356
+ 1. **`keep_releases`** (recommended):
357
+ ```json
358
+ {
359
+ "keep_releases": 5,
360
+ "delete_old": false
361
+ }
362
+ ```
363
+ - Keeps the 5 most recent releases
364
+ - Automatically removes older releases
365
+ - Works with shared assets cleanup
366
+
367
+ 2. **`delete_old`** (legacy):
368
+ ```json
369
+ {
370
+ "delete_old": true
371
+ }
372
+ ```
373
+ - Removes ALL old releases after each deployment
374
+ - Only keeps the current deployment
375
+ - Overrides `keep_releases` setting
376
+
377
+ **Cleanup Process:**
378
+
379
+ 1. **Release Cleanup**:
380
+ - Sorts releases by modification time (newest first)
381
+ - Keeps specified number of recent releases
382
+ - Removes older release directories completely
383
+
384
+ 2. **Shared Assets Cleanup** (when `enable_shared: true`):
385
+ - Scans all remaining release snapshots
386
+ - Collects all currently referenced hashed assets
387
+ - Removes unreferenced files from `shared/assets/`
388
+
389
+ **Example Cleanup Behavior:**
390
+
391
+ **Before cleanup (7 releases):**
392
+ ```
393
+ releases/
394
+ ├── 20260301_100000/ (oldest)
395
+ ├── 20260302_100000/
396
+ ├── 20260303_100000/
397
+ ├── 20260304_100000/
398
+ ├── 20260305_100000/
399
+ ├── 20260306_100000/
400
+ └── 20260307_100000/ (newest, current)
401
+ ```
402
+
403
+ **After cleanup (`keep_releases: 3`):**
404
+ ```
405
+ releases/
406
+ ├── 20260305_100000/ (kept)
407
+ ├── 20260306_100000/ (kept)
408
+ └── 20260307_100000/ (kept, current)
409
+ ```
410
+ *Older releases automatically removed*
411
+
412
+ **Monitoring Cleanup:**
193
413
  ```bash
194
- shipfe deploy --profile dev --all-sub
414
+ # Check current releases
415
+ ls -la releases/
416
+
417
+ # View cleanup logs in shipfe.log
418
+ tail -f shipfe.log | grep -i "cleanup\|remove"
419
+ ```
420
+
421
+ ## Configuration Best Practices
422
+
423
+ ### For Production Deployments
424
+
425
+ **Recommended Configuration:**
426
+ ```json
427
+ {
428
+ "enable_shared": true,
429
+ "keep_releases": 10,
430
+ "hashed_asset_patterns": [
431
+ "**/*.js",
432
+ "**/*.css",
433
+ "**/*.png",
434
+ "**/*.jpg",
435
+ "**/*.svg",
436
+ "**/*.woff2"
437
+ ]
438
+ }
439
+ ```
440
+
441
+ **Why this works:**
442
+ - Shared assets reduce disk usage by 60-80%
443
+ - 10 releases provide rollback capability
444
+ - Hashed patterns cover common static assets
445
+ - Automatic cleanup prevents disk space issues
446
+
447
+ ### For Development/Staging
448
+
449
+ **Recommended Configuration:**
450
+ ```json
451
+ {
452
+ "enable_shared": false,
453
+ "keep_releases": 3,
454
+ "delete_old": false
455
+ }
456
+ ```
457
+
458
+ **Why this works:**
459
+ - Faster deployments (no asset hashing)
460
+ - Fewer releases to manage
461
+ - Easier debugging without shared assets complexity
462
+
463
+ ### For Memory-Constrained Servers
464
+
465
+ **Recommended Configuration:**
466
+ ```json
467
+ {
468
+ "enable_shared": true,
469
+ "keep_releases": 2,
470
+ "hashed_asset_patterns": ["**/*.{js,css}"]
471
+ }
472
+ ```
473
+
474
+ **Why this works:**
475
+ - Minimal releases reduce storage
476
+ - Only essential assets shared
477
+ - Balances performance and disk usage
478
+
479
+ ## Troubleshooting
480
+
481
+ ### Common Issues
482
+
483
+ **1. Permission Denied Errors**
484
+ ```
485
+ Error: Permission denied (publickey)
486
+ ```
487
+ **Solutions:**
488
+ - Verify SSH key is added to `~/.ssh/authorized_keys` on server
489
+ - Check SSH key permissions: `chmod 600 ~/.ssh/id_rsa`
490
+ - Test SSH connection: `ssh user@host`
491
+
492
+ **2. Shared Assets Not Working**
493
+ ```
494
+ Warning: Failed to create hard link for shared asset
495
+ ```
496
+ **Solutions:**
497
+ - Ensure `enable_shared: true` in config
498
+ - Check server filesystem supports hard links
499
+ - Verify write permissions on shared directory
500
+
501
+ **3. Cleanup Not Working**
195
502
  ```
503
+ Warning: Failed to remove old release
504
+ ```
505
+ **Solutions:**
506
+ - Check file permissions on releases directory
507
+ - Ensure no processes are using old release files
508
+ - Verify `keep_releases` is set correctly
509
+
510
+ **4. Snapshot Creation Fails**
511
+ ```
512
+ Error: Failed to create snapshot
513
+ ```
514
+ **Solutions:**
515
+ - Check available disk space
516
+ - Verify write permissions on releases directory
517
+ - Ensure tar command is available on server
518
+
519
+ ### Debug Mode
520
+
521
+ Enable detailed logging:
522
+ ```bash
523
+ shipfe deploy --debug
524
+ ```
525
+
526
+ Check logs:
527
+ ```bash
528
+ tail -f shipfe.log
529
+ ```
530
+
531
+ ### Performance Optimization
532
+
533
+ **Slow Deployments:**
534
+ - Enable shared assets for large static files
535
+ - Use `hashed_asset_patterns` to target specific files
536
+ - Consider excluding large non-changing files from patterns
537
+
538
+ **High Disk Usage:**
539
+ - Reduce `keep_releases` count
540
+ - Enable shared assets
541
+ - Use `delete_old: true` for single-release deployments
196
542
 
197
- This will deploy to all sub-environments (admin, shop, cu) in sequence.
543
+ **Network Issues:**
544
+ - Compress large files before deployment
545
+ - Use faster SSH ciphers if supported
546
+ - Consider deploying during off-peak hours
547
+
548
+ ### Resource Snapshots
549
+
550
+ Each deployment generates a `shipfe.snapshot.json` file containing the complete manifest of deployed files and hashed assets. This snapshot provides full visibility into what was deployed and enables various operational capabilities.
551
+
552
+ **Example snapshot:**
553
+ ```json
554
+ {
555
+ "id": "20260303_035045",
556
+ "timestamp": "2026-03-03T03:50:45Z",
557
+ "files": [
558
+ "index.html",
559
+ "manifest.json",
560
+ "assets/app-abc123.js",
561
+ "assets/style-def456.css",
562
+ "assets/logo.png"
563
+ ],
564
+ "hashed_assets": [
565
+ "assets/app-abc123.js",
566
+ "assets/style-def456.css"
567
+ ]
568
+ }
569
+ ```
570
+
571
+ **Snapshot Fields:**
572
+ - **`id`**: Unique deployment identifier (timestamp-based)
573
+ - **`timestamp`**: ISO 8601 timestamp of deployment
574
+ - **`files`**: Complete list of all deployed files
575
+ - **`hashed_assets`**: Subset of files identified as hashed/cacheable assets
576
+
577
+ **Use Cases:**
578
+
579
+ 1. **Deployment Verification**:
580
+ ```bash
581
+ # Check what was deployed in a specific release
582
+ cat releases/20260303_035045/shipfe.snapshot.json
583
+ ```
584
+
585
+ 2. **Asset Inventory**:
586
+ ```bash
587
+ # List all hashed assets across all releases
588
+ find releases/ -name "shipfe.snapshot.json" -exec jq -r '.hashed_assets[]' {} \; | sort | uniq
589
+ ```
590
+
591
+ 3. **Rollback Validation**:
592
+ ```bash
593
+ # Verify rollback target has expected assets
594
+ jq '.files[]' releases/20260303_035045/shipfe.snapshot.json
595
+ ```
596
+
597
+ 4. **Storage Analysis**:
598
+ ```bash
599
+ # Calculate deployment sizes
600
+ find releases/20260303_035045/ -type f -exec ls -lh {} \; | awk '{sum += $5} END {print sum}'
601
+ ```
198
602
 
199
- Sub-environments inherit settings from the parent environment and can override `build_command`, `local_dist_path`, and `remote_deploy_path`.
603
+ **Integration with CI/CD:**
604
+ Snapshots enable automated verification in deployment pipelines:
605
+ - Compare deployed files against build artifacts
606
+ - Validate asset integrity post-deployment
607
+ - Generate deployment reports and changelogs
200
608
 
201
609
  ### Atomic Deployment
202
610
 
@@ -215,8 +623,16 @@ shipfe deploy --profile prod --atomic
215
623
  remote_deploy_path/
216
624
  ├── releases/
217
625
  │ ├── 20260303_034945/
626
+ │ │ ├── index.html
627
+ │ │ ├── assets/
628
+ │ │ │ └── app.js -> ../../../shared/assets/app-abc123.js
629
+ │ │ └── shipfe.snapshot.json
218
630
  │ ├── 20260303_035012/
219
631
  │ └── 20260303_035045/
632
+ ├── shared/
633
+ │ └── assets/
634
+ │ ├── app-abc123.js
635
+ │ └── style-def456.css
220
636
  └── current -> releases/20260303_035045
221
637
  ```
222
638
 
@@ -288,6 +704,10 @@ shipfe deploy --profile prod
288
704
  - SSH-based deployment
289
705
  - Automatic backup and rollback
290
706
  - Detailed logging
707
+ - Shared asset deduplication
708
+ - Resource snapshot generation
709
+ - Configurable release retention
710
+ - Automatic cleanup of unused assets
291
711
 
292
712
  ## License
293
713
 
package/README_CN.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Shipfe
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/shipfe.svg)](https://www.npmjs.com/package/shipfe)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![GitHub](https://img.shields.io/badge/GitHub-Master--Jian/shipfe--rust-blue.svg)](https://github.com/Master-Jian/shipfe-rust)
6
+
3
7
  一个强大的、**免费**、**基于 Rust** 的 Web 应用部署工具,**不请求网络**,实现**一键前端静态部署包上传到服务器**。支持多环境和子环境部署,具有零停机原子部署功能。
4
8
 
5
9
  ## 主要特性
@@ -13,6 +17,10 @@
13
17
  - 📦 **子环境支持**: 在同一服务器部署多个应用
14
18
  - 🔑 **灵活认证**: SSH 密钥、密码或环境变量认证
15
19
  - 📝 **详细日志**: 全面的部署日志用于故障排除
20
+ - 🗂️ **共享资源管理**: 跨发布版本去重哈希静态资源
21
+ - 📊 **资源快照**: 生成包含文件清单的部署快照
22
+ - 🧹 **自动清理**: 可配置的旧版本保留和未使用资源清理
23
+ - 🗑️ **共享资源重置**: 部署时自动清除所有共享资源,确保干净部署
16
24
 
17
25
  ## 安装
18
26
 
@@ -115,31 +123,117 @@ shipfe rollback --profile prod-admin --to 20260303_034945
115
123
  "port": 22,
116
124
  "username": "deploy",
117
125
  "password": "web1_password",
118
- "remote_deploy_path": "/var/www/prod",
119
- "delete_old": false
126
+ "remote_deploy_path": "/var/www/prod"
120
127
  },
121
128
  {
122
129
  "host": "web2.prod.com",
123
130
  "port": 22,
124
131
  "username": "deploy",
125
132
  "key_path": "/home/user/.ssh/web2_key",
126
- "remote_deploy_path": "/var/www/prod",
127
- "delete_old": false
133
+ "remote_deploy_path": "/var/www/prod"
128
134
  },
129
135
  {
130
136
  "host": "web3.prod.com",
131
137
  "port": 22,
132
138
  "username": "deploy",
133
- "remote_deploy_path": "/var/www/prod",
134
- "delete_old": false
139
+ "remote_deploy_path": "/var/www/prod"
135
140
  }
136
141
  ],
137
- "remote_tmp": "/tmp"
142
+ "remote_tmp": "/tmp",
143
+ "delete_old": false
138
144
  }
139
145
  }
140
146
  }
141
147
  ```
142
148
 
149
+ ### 配置项详解
150
+
151
+ 以下是 `shipfe.config.json` 中所有可用配置项的详细说明:
152
+
153
+ #### 全局配置项
154
+
155
+ - **`enable_shared`** (boolean, 默认: false)
156
+ - 是否启用共享资源管理
157
+ - 启用后,会对匹配的文件计算哈希并存储在共享目录中,避免重复上传
158
+ - 适用于频繁部署且有大量静态资源的应用
159
+
160
+ - **`hashed_asset_patterns`** (array of strings, 默认: [])
161
+ - 指定需要哈希处理的静态资源文件模式
162
+ - 支持 glob 模式,如 `"**/*.js"`, `"**/*.css"`, `"**/*.{png,jpg,svg}"`
163
+ - 只有匹配的文件会被哈希并共享,不匹配的文件每次部署都会重新上传
164
+
165
+ - **`keep_releases`** (number, 默认: 10)
166
+ - 保留的发布版本数量
167
+ - 超过此数量的旧发布会被自动清理
168
+ - 设置为 0 禁用自动清理
169
+
170
+ #### 环境配置项
171
+
172
+ 每个环境(如 `dev`, `prod`)可以包含以下配置:
173
+
174
+ - **`build_command`** (string, 必需)
175
+ - 本地构建命令,如 `"npm run build"` 或 `"yarn build"`
176
+
177
+ - **`local_dist_path`** (string, 必需)
178
+ - 本地构建输出目录路径,如 `"./dist"` 或 `"./build"`
179
+
180
+ - **`servers`** (array of objects, 必需)
181
+ - 服务器列表,每个服务器包含以下配置:
182
+ - **`host`** (string, 必需): 服务器主机名或 IP 地址
183
+ - **`port`** (number, 默认: 22): SSH 端口
184
+ - **`username`** (string, 必需): SSH 用户名
185
+ - **`password`** (string, 可选): SSH 密码(不推荐,建议使用密钥)
186
+ - **`key_path`** (string, 可选): SSH 私钥文件路径
187
+ - **`remote_deploy_path`** (string, 必需): 服务器上部署目录路径
188
+
189
+ - **`remote_tmp`** (string, 默认: "/tmp")
190
+ - 服务器上的临时目录路径,用于上传文件
191
+
192
+ - **`sub_environments`** (object, 可选)
193
+ - 子环境配置,键为子环境名称,值为子环境配置对象
194
+ - 子环境会继承父环境的设置,但可以覆盖 `build_command`, `local_dist_path`, `remote_deploy_path`
195
+
196
+ - **`delete_old`** (boolean, 默认: false)
197
+ - 是否在每次部署后删除所有旧发布
198
+ - 只保留当前部署
199
+ - 覆盖 `keep_releases` 设置
200
+
201
+ #### 共享资源和哈希配置说明
202
+
203
+ **共享资源的工作原理:**
204
+
205
+ 1. **文件匹配**: 根据 `hashed_asset_patterns` 匹配文件
206
+ 2. **哈希计算**: 对匹配文件计算 SHA256 哈希值
207
+ 3. **存储策略**:
208
+ - 相同哈希的文件只存储一次在 `shared/assets/` 目录
209
+ - 文件名格式为 `{hash}.{ext}`,如 `abc123def456.js`
210
+ 4. **链接创建**: 在发布目录中创建硬链接指向共享文件
211
+ 5. **清理机制**: 删除不再被任何发布引用的共享文件
212
+
213
+ **配置示例和解释:**
214
+
215
+ ```json
216
+ {
217
+ "enable_shared": true,
218
+ "hashed_asset_patterns": [
219
+ "**/*.js", // 匹配所有 JS 文件
220
+ "**/*.css", // 匹配所有 CSS 文件
221
+ "**/*.{png,jpg}", // 匹配 PNG 和 JPG 文件
222
+ "!**/vendor/**" // 排除 vendor 目录(如果不需要共享)
223
+ ],
224
+ "keep_releases": 5
225
+ }
226
+ ```
227
+
228
+ **适用场景:**
229
+ - **启用共享**: 大型应用,频繁部署,有很多静态资源
230
+ - **禁用共享**: 小型应用,部署不频繁,或需要简单调试
231
+
232
+ **注意事项:**
233
+ - 共享资源需要服务器文件系统支持硬链接
234
+ - 首次启用共享时,所有匹配文件都会被哈希处理
235
+ - 禁用共享后,已有的共享文件不会被删除,需要手动清理
236
+
143
237
  ### 子环境
144
238
 
145
239
  对于在同一服务器部署多个应用或不同配置,使用子环境:
@@ -222,6 +316,182 @@ remote_deploy_path/
222
316
 
223
317
  您的 Web 服务器应从 `remote_deploy_path/current` 提供服务。
224
318
 
319
+ ## 共享资源管理
320
+
321
+ Shipfe 支持跨多个发布版本共享静态资源,通过文件哈希去重来减少磁盘使用和网络传输。
322
+
323
+ **启用共享资源:**
324
+ ```json
325
+ {
326
+ "environments": {
327
+ "prod": {
328
+ "enable_shared": true,
329
+ "hashed_asset_patterns": [
330
+ "**/*.js",
331
+ "**/*.css",
332
+ "**/*.png",
333
+ "**/*.jpg",
334
+ "**/*.svg",
335
+ "**/*.woff2"
336
+ ],
337
+ "servers": [...]
338
+ }
339
+ }
340
+ }
341
+ ```
342
+
343
+ **工作原理:**
344
+
345
+ 1. **文件哈希计算**:对匹配模式的文件计算 SHA256 哈希
346
+ 2. **共享存储**:将哈希文件存储在 `shared/assets/` 目录
347
+ 3. **硬链接创建**:在发布目录中创建指向共享文件的硬链接
348
+ 4. **自动清理**:删除未被任何发布引用的共享文件
349
+
350
+ **共享资源重置:**
351
+
352
+ 在每次部署开始时,Shipfe 会自动清除 `shared/` 目录下的所有现有资源,然后重新创建 `shared/assets/` 目录。这确保了每次部署从干净的状态开始,避免了旧资源的积累和潜在冲突。
353
+
354
+ **目录结构示例:**
355
+ ```
356
+ remote_deploy_path/
357
+ ├── shared/
358
+ │ └── assets/
359
+ │ ├── abc123def456.js
360
+ │ ├── def789ghi012.css
361
+ │ └── hij345klm678.png
362
+ ├── releases/
363
+ │ ├── 20260304_120000/
364
+ │ │ ├── index.html
365
+ │ │ ├── app.js -> ../../shared/assets/abc123def456.js
366
+ │ │ └── styles.css -> ../../shared/assets/def789ghi012.css
367
+ │ └── 20260304_120100/
368
+ │ ├── index.html
369
+ │ ├── app.js -> ../../shared/assets/abc123def456.js
370
+ │ └── styles.css -> ../../shared/assets/def789ghi012.css
371
+ └── current -> releases/20260304_120100
372
+ ```
373
+
374
+ **优势:**
375
+ - **减少磁盘使用**:相同文件只存储一次
376
+ - **加快部署**:未更改的文件不需要重新上传
377
+ - **节省带宽**:只传输新的或更改的文件
378
+ - **原子更新**:所有硬链接同时创建,确保一致性
379
+
380
+ ## 资源快照
381
+
382
+ 每个发布都会生成包含完整文件清单的快照,用于审计和回滚验证。
383
+
384
+ **快照内容:**
385
+ - 所有部署文件及其哈希值
386
+ - 共享资源引用
387
+ - 部署时间戳和元数据
388
+ - 文件权限和大小信息
389
+
390
+ **快照文件位置:**
391
+ ```
392
+ releases/20260304_120100/
393
+ ├── files/
394
+ │ ├── index.html
395
+ │ └── app.js -> ../../shared/assets/abc123def456.js
396
+ ├── snapshot.json
397
+ └── metadata.json
398
+ ```
399
+
400
+ **快照示例:**
401
+ ```json
402
+ {
403
+ "timestamp": "20260304_120100",
404
+ "files": {
405
+ "index.html": {
406
+ "hash": "a1b2c3d4e5f6...",
407
+ "size": 1024,
408
+ "permissions": "644"
409
+ },
410
+ "app.js": {
411
+ "shared_hash": "abc123def456.js",
412
+ "size": 51200,
413
+ "permissions": "644"
414
+ }
415
+ },
416
+ "metadata": {
417
+ "build_command": "npm run build",
418
+ "deployed_by": "user",
419
+ "deployed_at": "2026-03-04T12:01:00Z"
420
+ }
421
+ }
422
+ ```
423
+
424
+ ## 自动清理
425
+
426
+ Shipfe 提供可配置的自动清理旧发布和未使用共享资源功能,以有效管理磁盘使用。
427
+
428
+ **配置选项:**
429
+
430
+ 1. **`keep_releases`**(推荐):
431
+ ```json
432
+ {
433
+ "keep_releases": 5,
434
+ "delete_old": false
435
+ }
436
+ ```
437
+ - 保留最近的 5 个发布
438
+ - 自动删除旧发布
439
+ - 与共享资源清理配合工作
440
+
441
+ 2. **`delete_old`**(传统):
442
+ ```json
443
+ {
444
+ "delete_old": true
445
+ }
446
+ ```
447
+ - 在每次部署后删除所有旧发布
448
+ - 只保留当前部署
449
+ - 覆盖 `keep_releases` 设置
450
+
451
+ **清理过程:**
452
+
453
+ 1. **发布清理**:
454
+ - 按修改时间排序发布(最新优先)
455
+ - 保留指定数量的最近发布
456
+ - 完全删除旧发布目录
457
+
458
+ 2. **共享资源清理**(当 `enable_shared: true` 时):
459
+ - 扫描所有剩余发布快照
460
+ - 收集当前被引用的所有哈希资源
461
+ - 从 `shared/assets/` 删除未引用的文件
462
+
463
+ **清理行为示例:**
464
+
465
+ **清理前(7 个发布):**
466
+ ```
467
+ releases/
468
+ ├── 20260301_100000/ (最旧)
469
+ ├── 20260302_100000/
470
+ ├── 20260303_100000/
471
+ ├── 20260304_100000/
472
+ ├── 20260305_100000/
473
+ ├── 20260306_100000/
474
+ └── 20260307_100000/ (最新,当前)
475
+ ```
476
+
477
+ **清理后(`keep_releases: 3`):**
478
+ ```
479
+ releases/
480
+ ├── 20260305_100000/ (保留)
481
+ ├── 20260306_100000/ (保留)
482
+ └── 20260307_100000/ (保留,当前)
483
+ ```
484
+ *旧发布自动删除*
485
+
486
+ **监控清理:**
487
+ ```bash
488
+ # 检查当前发布
489
+ ls -la releases/
490
+
491
+ # 在 shipfe.log 中查看清理日志
492
+ tail -f shipfe.log | grep -i "cleanup\|remove"
493
+ ```
494
+
225
495
  **或为所有服务器使用环境变量:**
226
496
  ```bash
227
497
  export SSH_PRIVATE_KEY="$(cat ~/.ssh/prod_key)"
@@ -280,6 +550,133 @@ shipfe deploy --profile prod
280
550
  }
281
551
  ```
282
552
 
553
+ ## 配置最佳实践
554
+
555
+ ### 生产环境部署
556
+
557
+ **推荐配置:**
558
+ ```json
559
+ {
560
+ "enable_shared": true,
561
+ "keep_releases": 10,
562
+ "hashed_asset_patterns": [
563
+ "**/*.js",
564
+ "**/*.css",
565
+ "**/*.png",
566
+ "**/*.jpg",
567
+ "**/*.svg",
568
+ "**/*.woff2"
569
+ ]
570
+ }
571
+ ```
572
+
573
+ **为什么有效:**
574
+ - 共享资源将磁盘使用减少 60-80%
575
+ - 10 个发布提供回滚能力
576
+ - 哈希模式覆盖常见静态资源
577
+ - 自动清理防止磁盘空间问题
578
+
579
+ ### 开发/预发布环境
580
+
581
+ **推荐配置:**
582
+ ```json
583
+ {
584
+ "enable_shared": false,
585
+ "keep_releases": 3,
586
+ "delete_old": false
587
+ }
588
+ ```
589
+
590
+ **为什么有效:**
591
+ - 部署更快(无资源哈希)
592
+ - 更少的发布需要管理
593
+ - 无共享资源复杂性,更易调试
594
+
595
+ ### 内存受限服务器
596
+
597
+ **推荐配置:**
598
+ ```json
599
+ {
600
+ "enable_shared": true,
601
+ "keep_releases": 2,
602
+ "hashed_asset_patterns": ["**/*.{js,css}"]
603
+ }
604
+ ```
605
+
606
+ **为什么有效:**
607
+ - 最少的发布减少存储
608
+ - 只共享必要资源
609
+ - 平衡性能和磁盘使用
610
+
611
+ ## 故障排除
612
+
613
+ ### 常见问题
614
+
615
+ **1. 权限拒绝错误**
616
+ ```
617
+ Error: Permission denied (publickey)
618
+ ```
619
+ **解决方案:**
620
+ - 验证 SSH 密钥已添加到服务器的 `~/.ssh/authorized_keys`
621
+ - 检查 SSH 密钥权限:`chmod 600 ~/.ssh/id_rsa`
622
+ - 测试 SSH 连接:`ssh user@host`
623
+
624
+ **2. 共享资源不工作**
625
+ ```
626
+ Warning: Failed to create hard link for shared asset
627
+ ```
628
+ **解决方案:**
629
+ - 确保配置中 `enable_shared: true`
630
+ - 检查服务器文件系统支持硬链接
631
+ - 验证 shared 目录的写入权限
632
+
633
+ **3. 清理不工作**
634
+ ```
635
+ Warning: Failed to remove old release
636
+ ```
637
+ **解决方案:**
638
+ - 检查 releases 目录的文件权限
639
+ - 确保没有进程正在使用旧发布文件
640
+ - 验证 `keep_releases` 设置正确
641
+
642
+ **4. 快照创建失败**
643
+ ```
644
+ Error: Failed to create snapshot
645
+ ```
646
+ **解决方案:**
647
+ - 检查可用磁盘空间
648
+ - 验证 releases 目录的写入权限
649
+ - 确保服务器上有 tar 命令
650
+
651
+ ### 调试模式
652
+
653
+ 启用详细日志:
654
+ ```bash
655
+ shipfe deploy --debug
656
+ ```
657
+
658
+ 检查日志:
659
+ ```bash
660
+ tail -f shipfe.log
661
+ ```
662
+
663
+ ### 性能优化
664
+
665
+ **部署缓慢:**
666
+ - 为大静态文件启用共享资源
667
+ - 使用 `hashed_asset_patterns` 针对特定文件
668
+ - 考虑从模式中排除大的非更改文件
669
+
670
+ **磁盘使用过高:**
671
+ - 减少 `keep_releases` 数量
672
+ - 启用共享资源
673
+ - 对单发布部署使用 `delete_old: true`
674
+
675
+ **网络问题:**
676
+ - 部署前压缩大文件
677
+ - 如果支持,使用更快的 SSH 密码
678
+ - 考虑在非高峰时段部署
679
+
283
680
  ## 功能特性
284
681
 
285
682
  - 多环境支持
package/bin/shipfe CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shipfe",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "A deployment tool for web applications",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -23,6 +23,10 @@
23
23
  "ci-cd"
24
24
  ],
25
25
  "author": "Jans",
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "https://github.com/Master-Jian/shipfe-rust.git"
29
+ },
26
30
  "license": "MIT",
27
31
  "os": [
28
32
  "darwin",