@gravito/launchpad 1.2.1 → 1.3.1
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/CHANGELOG.md +55 -0
- package/README.md +51 -43
- package/README.zh-TW.md +110 -0
- package/dist/index.d.mts +324 -7
- package/dist/index.d.ts +324 -7
- package/dist/index.js +407 -29
- package/dist/index.mjs +395 -29
- package/package.json +7 -5
- package/scripts/check-coverage.ts +64 -0
- package/src/Application/MissionQueue.ts +143 -0
- package/src/Application/PoolManager.ts +170 -18
- package/src/Application/RefurbishUnit.ts +24 -12
- package/src/Domain/Events.ts +46 -0
- package/src/Domain/Interfaces.ts +82 -0
- package/src/Domain/Rocket.ts +18 -0
- package/src/Infrastructure/Docker/DockerAdapter.ts +80 -3
- package/src/Infrastructure/Git/ShellGitAdapter.ts +1 -1
- package/src/index.ts +3 -0
- package/tests/Deployment.test.ts +3 -1
- package/tests/pool-manager.test.ts +3 -1
- package/tests/resource-limits.test.ts +241 -0
- package/tsconfig.json +14 -26
- package/.turbo/turbo-build.log +0 -18
- package/.turbo/turbo-test$colon$coverage.log +0 -183
- package/.turbo/turbo-test.log +0 -100
- package/.turbo/turbo-typecheck.log +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,60 @@
|
|
|
1
1
|
# @gravito/launchpad
|
|
2
2
|
|
|
3
|
+
## 1.3.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [5a7f332]
|
|
8
|
+
- @gravito/ripple@4.0.0
|
|
9
|
+
|
|
10
|
+
## 1.3.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- **P0 緊急修復:資源限制與隊列機制**
|
|
15
|
+
- 新增 `PoolConfig` 配置介面,支援 `maxRockets`、`maxQueueSize`、`queueTimeoutMs` 等參數
|
|
16
|
+
- 實現 `MissionQueue` 任務隊列管理,支援 FIFO 排程和超時處理
|
|
17
|
+
- 重構 `PoolManager.assignMission()`,加入三種資源耗盡策略:
|
|
18
|
+
- `queue`:任務進入等待隊列(預設)
|
|
19
|
+
- `reject`:立即拒絕新任務
|
|
20
|
+
- `dynamic`:有限度的動態建立容器
|
|
21
|
+
- 新增 Pool 狀態查詢 API:`getPoolStatus()`、`getQueueStats()`
|
|
22
|
+
- 新增領域事件:`PoolExhausted`、`MissionQueued`、`MissionQueueTimeout`
|
|
23
|
+
- 修改 `RefurbishConfig`,支援自訂清理命令和失敗處理策略
|
|
24
|
+
|
|
25
|
+
### Features
|
|
26
|
+
|
|
27
|
+
- **資源保護機制**:防止 Rocket 無限增長導致系統資源耗盡
|
|
28
|
+
- **任務隊列**:當 Pool 耗盡時,新任務自動進入隊列等待
|
|
29
|
+
- **可配置策略**:支援多種資源管理策略,適應不同使用場景
|
|
30
|
+
- **深度清理優化**:改進容器清理邏輯,減少髒污風險
|
|
31
|
+
|
|
32
|
+
### Breaking Changes
|
|
33
|
+
|
|
34
|
+
- `PoolManager` 構造函數新增可選的 `config` 參數
|
|
35
|
+
- `RefurbishUnit` 構造函數新增可選的 `config` 參數
|
|
36
|
+
- `warmup()` 方法的 `count` 參數改為可選,預設使用配置值
|
|
37
|
+
|
|
38
|
+
### Migration Guide
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
// 舊版(仍然有效)
|
|
42
|
+
const manager = new PoolManager(docker, repo);
|
|
43
|
+
|
|
44
|
+
// 新版(可選配置)
|
|
45
|
+
const manager = new PoolManager(docker, repo, refurbish, router, {
|
|
46
|
+
maxRockets: 10,
|
|
47
|
+
exhaustionStrategy: "queue",
|
|
48
|
+
maxQueueSize: 50,
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 1.2.2
|
|
53
|
+
|
|
54
|
+
### Patch Changes
|
|
55
|
+
|
|
56
|
+
- 905588f: fix: replace insecure Math.random() with crypto.randomUUID() for ID and temporary path generation (CWE-330)
|
|
57
|
+
|
|
3
58
|
## 1.2.1
|
|
4
59
|
|
|
5
60
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -12,26 +12,31 @@
|
|
|
12
12
|
- **♻️ Auto-Recycling**: Containers are automatically refurbished and returned to the pool after missions.
|
|
13
13
|
- **🤖 GitHub Integration**: Built-in webhook handler for PR previews and automated comments.
|
|
14
14
|
- **🛡️ Secure Isolation**: Each deployment runs in an isolated container environment.
|
|
15
|
+
- **📡 Real-time Telemetry**: Integrated with `@gravito/ripple` for live deployment progress updates via WebSockets.
|
|
16
|
+
- **🕸️ Dynamic Proxying**: High-performance routing to active deployments using Bun's native HTTP capabilities.
|
|
15
17
|
|
|
16
18
|
## 🏗️ Architecture Overview
|
|
17
19
|
|
|
18
|
-
Launchpad follows **Clean Architecture** principles
|
|
20
|
+
Launchpad follows **Clean Architecture** principles and is implemented as a **Gravito Orbit**:
|
|
19
21
|
|
|
20
|
-
### Domain Layer
|
|
21
|
-
- **Rocket**: The aggregate root representing a container instance.
|
|
22
|
-
- **Mission**: Represents a deployment task (
|
|
23
|
-
- **Status Machine**: Strictly manages transitions (Idle -> Assigned -> Deployed -> Recycling).
|
|
22
|
+
### Domain Layer (`src/Domain`)
|
|
23
|
+
- **Rocket**: The aggregate root representing a container instance and its lifecycle state.
|
|
24
|
+
- **Mission**: Represents a deployment task (repository URL, commit SHA, branch).
|
|
25
|
+
- **Status Machine**: Strictly manages transitions (`Idle` -> `Assigned` -> `Deployed` -> `Recycling`).
|
|
26
|
+
- **Events**: Domain events for tracking lifecycle changes.
|
|
24
27
|
|
|
25
|
-
### Application Layer
|
|
28
|
+
### Application Layer (`src/Application`)
|
|
26
29
|
- **PoolManager**: Orchestrates the lifecycle of Rockets (warmup, assignment, recycling).
|
|
27
|
-
- **
|
|
28
|
-
- **
|
|
29
|
-
- **RefurbishUnit**: Cleans up used containers for
|
|
30
|
+
- **MissionControl**: High-level facade for launching missions and coordinating injection.
|
|
31
|
+
- **PayloadInjector**: Handles the git operations and the physical injection of code into containers.
|
|
32
|
+
- **RefurbishUnit**: Cleans up and resets used containers for return to the pool.
|
|
30
33
|
|
|
31
|
-
### Infrastructure Layer
|
|
32
|
-
- **DockerAdapter**: Low-level communication with Docker daemon.
|
|
34
|
+
### Infrastructure Layer (`src/Infrastructure`)
|
|
35
|
+
- **DockerAdapter**: Low-level communication with the Docker daemon.
|
|
33
36
|
- **ShellGitAdapter**: Git operations via shell commands.
|
|
34
|
-
- **
|
|
37
|
+
- **OctokitGitHubAdapter**: Interaction with GitHub API for status updates and PR comments.
|
|
38
|
+
- **CachedRocketRepository**: Persistent storage for Rocket states using `@gravito/stasis`.
|
|
39
|
+
- **BunProxyAdapter**: Manages reverse proxying to active containers with sub-millisecond overhead.
|
|
35
40
|
|
|
36
41
|
## 🚀 Quick Start
|
|
37
42
|
|
|
@@ -41,55 +46,58 @@ Launchpad follows **Clean Architecture** principles:
|
|
|
41
46
|
bun add @gravito/launchpad
|
|
42
47
|
```
|
|
43
48
|
|
|
44
|
-
### Basic Usage
|
|
49
|
+
### Basic Usage (As an Orbit)
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
import { PoolManager, PayloadInjector, Mission } from '@gravito/launchpad'
|
|
48
|
-
import { DockerAdapter, ShellGitAdapter, InMemoryRocketRepository } from '@gravito/launchpad/infra'
|
|
49
|
-
|
|
50
|
-
// Initialize adapters
|
|
51
|
-
const docker = new DockerAdapter()
|
|
52
|
-
const repo = new InMemoryRocketRepository()
|
|
53
|
-
const manager = new PoolManager(docker, repo)
|
|
54
|
-
|
|
55
|
-
// 1. Warmup the pool (Create 3 idle containers)
|
|
56
|
-
await manager.warmup(3)
|
|
51
|
+
The most common way to use Launchpad is as part of a Gravito application:
|
|
57
52
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
53
|
+
```typescript
|
|
54
|
+
import { PlanetCore } from '@gravito/core'
|
|
55
|
+
import { OrbitCache } from '@gravito/stasis'
|
|
56
|
+
import { OrbitRipple } from '@gravito/ripple'
|
|
57
|
+
import { LaunchpadOrbit } from '@gravito/launchpad'
|
|
58
|
+
|
|
59
|
+
const ripple = new OrbitRipple({ path: '/ws' })
|
|
60
|
+
|
|
61
|
+
const core = await PlanetCore.boot({
|
|
62
|
+
orbits: [
|
|
63
|
+
new OrbitCache(),
|
|
64
|
+
ripple,
|
|
65
|
+
new LaunchpadOrbit(ripple)
|
|
66
|
+
],
|
|
63
67
|
})
|
|
64
68
|
|
|
65
|
-
|
|
66
|
-
const rocket = await manager.assignMission(mission)
|
|
67
|
-
const injector = new PayloadInjector(docker, new ShellGitAdapter())
|
|
68
|
-
await injector.deploy(rocket)
|
|
69
|
-
|
|
70
|
-
console.log(`Mission deployed to http://localhost:${rocket.port}`)
|
|
69
|
+
await core.bootstrap()
|
|
71
70
|
```
|
|
72
71
|
|
|
73
|
-
###
|
|
74
|
-
|
|
75
|
-
Launchpad can run as a Gravito Orbit, providing a REST API and Webhook support.
|
|
72
|
+
### Manual Mission Launch
|
|
76
73
|
|
|
77
74
|
```typescript
|
|
78
|
-
import {
|
|
75
|
+
import { MissionControl, Mission } from '@gravito/launchpad'
|
|
76
|
+
|
|
77
|
+
// Assuming container is available via Gravito Core
|
|
78
|
+
const ctrl = container.make<MissionControl>('launchpad.ctrl')
|
|
79
|
+
|
|
80
|
+
const mission = Mission.create({
|
|
81
|
+
id: 'mission-123',
|
|
82
|
+
repoUrl: 'https://github.com/example/repo.git',
|
|
83
|
+
branch: 'main'
|
|
84
|
+
})
|
|
79
85
|
|
|
80
|
-
const
|
|
81
|
-
console.log(`
|
|
86
|
+
const rocketId = await ctrl.launch(mission, (type, data) => {
|
|
87
|
+
console.log(`[Telemetry] ${type}:`, data)
|
|
88
|
+
})
|
|
82
89
|
```
|
|
83
90
|
|
|
84
91
|
## ⚙️ Configuration
|
|
85
92
|
|
|
86
|
-
Launchpad relies on
|
|
93
|
+
Launchpad relies on a working Docker environment.
|
|
87
94
|
|
|
88
95
|
| Environment Variable | Description | Default |
|
|
89
96
|
|----------------------|-------------|---------|
|
|
90
97
|
| `GITHUB_TOKEN` | Token for GitHub API access | (Required for PR comments) |
|
|
91
98
|
| `GITHUB_WEBHOOK_SECRET` | Secret for verifying webhooks | (Optional) |
|
|
92
99
|
| `POOL_SIZE` | Target number of pre-warmed containers | `3` |
|
|
100
|
+
| `CACHE_DRIVER` | Storage driver for Rocket states | `file` |
|
|
93
101
|
|
|
94
102
|
## 🧪 Testing
|
|
95
103
|
|
|
@@ -99,4 +107,4 @@ bun test
|
|
|
99
107
|
|
|
100
108
|
## 📄 License
|
|
101
109
|
|
|
102
|
-
MIT © Gravito Framework
|
|
110
|
+
MIT © Gravito Framework
|
package/README.zh-TW.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# @gravito/launchpad (繁體中文)
|
|
2
|
+
|
|
3
|
+
> 🚀 Bun 專用的即時部署系統。容器生命週期管理與零停機部署。
|
|
4
|
+
|
|
5
|
+
**Gravito Launchpad** 是專為 Bun 執行環境設計的協調系統。它採用獨特的「火箭池 (Rocket Pool)」架構來預熱容器,透過將程式碼直接注入已運行的實例而非重新構建映像檔,實現亞秒級 (sub-second) 的快速部署。
|
|
6
|
+
|
|
7
|
+
## ✨ 核心特性
|
|
8
|
+
|
|
9
|
+
- **🔥 火箭池 (Rocket Pool)**:預熱容器池,消除冷啟動時間。
|
|
10
|
+
- **💉 載荷注入 (Payload Injection)**:跳過 `docker build`。透過 `docker cp` 在毫秒內完成程式碼注入。
|
|
11
|
+
- **🏗️ DDD 架構**:基於 `@gravito/enterprise` 構建,具備嚴謹的狀態機管理。
|
|
12
|
+
- **♻️ 自動回收**:任務完成後,容器會自動翻新並返回池中供後續使用。
|
|
13
|
+
- **🤖 GitHub 整合**:內建 Webhook 處理程序,支持 PR 預覽部署與自動化評論。
|
|
14
|
+
- **🛡️ 安全隔離**:每個部署都在隔離的容器環境中運行。
|
|
15
|
+
- **📡 即時遙測**:整合 `@gravito/ripple`,透過 WebSockets 提供部署進度的即時更新。
|
|
16
|
+
- **🕸️ 動態代理**:利用 Bun 原生 HTTP 能力,為活動部署提供高性能路由。
|
|
17
|
+
|
|
18
|
+
## 🏗️ 架構概覽
|
|
19
|
+
|
|
20
|
+
Launchpad 遵循 **整潔架構 (Clean Architecture)** 原則,並作為一個 **Gravito Orbit** 實作:
|
|
21
|
+
|
|
22
|
+
### 領域層 (Domain Layer - `src/Domain`)
|
|
23
|
+
- **Rocket (火箭)**:代表容器實例及其生命週期狀態的聚合根 (Aggregate Root)。
|
|
24
|
+
- **Mission (任務)**:代表部署任務(儲存庫 URL、Commit SHA、分支)。
|
|
25
|
+
- **Status Machine (狀態機)**:嚴格管理狀態轉換 (`Idle` -> `Assigned` -> `Deployed` -> `Recycling`)。
|
|
26
|
+
- **Events (事件)**:用於追蹤生命週期變化的領域事件。
|
|
27
|
+
|
|
28
|
+
### 應用層 (Application Layer - `src/Application`)
|
|
29
|
+
- **PoolManager (池管理器)**:協調火箭的生命週期(預熱、分配、回收)。
|
|
30
|
+
- **MissionControl (任務控制中心)**:啟動任務並協調注入的高層外觀 (Facade)。
|
|
31
|
+
- **PayloadInjector (載荷注入器)**:處理 Git 操作及將程式碼物理注入容器。
|
|
32
|
+
- **RefurbishUnit (翻新單元)**:清理並重置已使用的容器以返回池中。
|
|
33
|
+
|
|
34
|
+
### 基礎設施層 (Infrastructure Layer - `src/Infrastructure`)
|
|
35
|
+
- **DockerAdapter**:與 Docker 守護進程的低階通訊。
|
|
36
|
+
- **ShellGitAdapter**:透過 Shell 指令進行 Git 操作。
|
|
37
|
+
- **OctokitGitHubAdapter**:與 GitHub API 互動以更新狀態及發佈 PR 評論。
|
|
38
|
+
- **CachedRocketRepository**:使用 `@gravito/stasis` 持久化火箭狀態。
|
|
39
|
+
- **BunProxyAdapter**:為活動容器提供亞毫秒級開銷的反向代理。
|
|
40
|
+
|
|
41
|
+
## 🚀 快速上手
|
|
42
|
+
|
|
43
|
+
### 安裝
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
bun add @gravito/launchpad
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 基本用法 (作為 Orbit)
|
|
50
|
+
|
|
51
|
+
在 Gravito 應用中使用 Launchpad 的最常見方式:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { PlanetCore } from '@gravito/core'
|
|
55
|
+
import { OrbitCache } from '@gravito/stasis'
|
|
56
|
+
import { OrbitRipple } from '@gravito/ripple'
|
|
57
|
+
import { LaunchpadOrbit } from '@gravito/launchpad'
|
|
58
|
+
|
|
59
|
+
const ripple = new OrbitRipple({ path: '/ws' })
|
|
60
|
+
|
|
61
|
+
const core = await PlanetCore.boot({
|
|
62
|
+
orbits: [
|
|
63
|
+
new OrbitCache(),
|
|
64
|
+
ripple,
|
|
65
|
+
new LaunchpadOrbit(ripple)
|
|
66
|
+
],
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
await core.bootstrap()
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 手動啟動任務
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { MissionControl, Mission } from '@gravito/launchpad'
|
|
76
|
+
|
|
77
|
+
// 假設容器已透過 Gravito Core 提供
|
|
78
|
+
const ctrl = container.make<MissionControl>('launchpad.ctrl')
|
|
79
|
+
|
|
80
|
+
const mission = Mission.create({
|
|
81
|
+
id: 'mission-123',
|
|
82
|
+
repoUrl: 'https://github.com/example/repo.git',
|
|
83
|
+
branch: 'main'
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const rocketId = await ctrl.launch(mission, (type, data) => {
|
|
87
|
+
console.log(`[遙測] ${type}:`, data)
|
|
88
|
+
})
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## ⚙️ 配置
|
|
92
|
+
|
|
93
|
+
Launchpad 依賴於運作正常的 Docker 環境。
|
|
94
|
+
|
|
95
|
+
| 環境變數 | 說明 | 預設值 |
|
|
96
|
+
|----------------------|-------------|---------|
|
|
97
|
+
| `GITHUB_TOKEN` | GitHub API 存取權杖 | (PR 評論必填) |
|
|
98
|
+
| `GITHUB_WEBHOOK_SECRET` | 驗證 Webhook 的密鑰 | (選填) |
|
|
99
|
+
| `POOL_SIZE` | 預熱容器的目標數量 | `3` |
|
|
100
|
+
| `CACHE_DRIVER` | 火箭狀態的儲存驅動 | `file` |
|
|
101
|
+
|
|
102
|
+
## 🧪 測試
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
bun test
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## 📄 授權
|
|
109
|
+
|
|
110
|
+
MIT © Gravito Framework
|