@optima-chat/dev-skills 0.7.15 → 0.7.17
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/.claude/commands/restart-ecs.md +196 -0
- package/.claude/skills/restart-ecs/SKILL.md +160 -0
- package/.claude/skills/show-env/SKILL.md +185 -0
- package/README.md +10 -5
- package/bin/helpers/show-env.ts +183 -0
- package/dist/bin/helpers/show-env.js +145 -0
- package/package.json +3 -2
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# /restart-ecs - 重启 ECS 服务
|
|
2
|
+
|
|
3
|
+
快速重启 ECS 集群中的服务,支持 Stage/Prod 两个环境。
|
|
4
|
+
|
|
5
|
+
**版本**: v0.1.0
|
|
6
|
+
|
|
7
|
+
## 使用场景
|
|
8
|
+
|
|
9
|
+
**后端开发者**: 代码更新后需要重启服务使配置生效
|
|
10
|
+
**DevOps**: 服务异常需要快速恢复
|
|
11
|
+
**排查问题**: 服务状态异常,需要重启清理缓存或连接
|
|
12
|
+
|
|
13
|
+
## 用法
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
/restart-ecs <service> [environment]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 参数
|
|
20
|
+
|
|
21
|
+
- `service` (必需): 服务简称
|
|
22
|
+
- `user-auth` - 用户认证服务
|
|
23
|
+
- `user-auth-admin` - 用户认证管理后台
|
|
24
|
+
- `commerce-backend` - 电商后端 API
|
|
25
|
+
- `commerce-rq-worker` - RQ 后台任务
|
|
26
|
+
- `commerce-rq-scheduler` - RQ 定时调度
|
|
27
|
+
- `agentic-chat` - AI 聊天服务
|
|
28
|
+
- `session-gateway` - AI Shell 网关
|
|
29
|
+
- `bi-backend` - BI 后端
|
|
30
|
+
- `bi-dashboard` - BI 仪表板
|
|
31
|
+
- `optima-scout` - 产品研究工具
|
|
32
|
+
- `ai-shell-web-ui` - Shell Web UI
|
|
33
|
+
- `optima-store` - 商城前端(仅 Stage)
|
|
34
|
+
- `pgbouncer` - 连接池(仅 Stage)
|
|
35
|
+
- `environment` (可选): 环境,默认 stage
|
|
36
|
+
- `stage` - Stage 预发布环境(默认,更安全)
|
|
37
|
+
- `prod` - 生产环境(需确认)
|
|
38
|
+
|
|
39
|
+
## 示例
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
/restart-ecs session-gateway # 重启 Stage 环境的 session-gateway(默认)
|
|
43
|
+
/restart-ecs session-gateway prod # 重启 Prod 环境的 session-gateway
|
|
44
|
+
/restart-ecs user-auth stage # 重启 Stage 环境的 user-auth
|
|
45
|
+
/restart-ecs list # 列出 Stage 环境所有可用服务
|
|
46
|
+
/restart-ecs list prod # 列出 Prod 环境所有可用服务
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 特殊参数处理
|
|
50
|
+
|
|
51
|
+
- 如果用户输入 `/restart-ecs` 或 `/restart-ecs --help` 或 `/restart-ecs help`,显示此帮助文档
|
|
52
|
+
- 如果用户输入 `/restart-ecs list [env]`,列出指定环境的所有服务
|
|
53
|
+
|
|
54
|
+
## Claude Code 执行步骤
|
|
55
|
+
|
|
56
|
+
### 0. 列出服务(service = "list")
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# 列出 Stage 环境服务
|
|
60
|
+
aws ecs list-services --cluster optima-stage-cluster --region ap-southeast-1 --query 'serviceArns[*]' --output text | tr '\t' '\n' | sed 's/.*service\/optima-stage-cluster\///'
|
|
61
|
+
|
|
62
|
+
# 列出 Prod 环境服务
|
|
63
|
+
aws ecs list-services --cluster optima-prod-cluster --region ap-southeast-1 --query 'serviceArns[*]' --output text | tr '\t' '\n' | sed 's/.*service\/optima-prod-cluster\///'
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 1. Stage 环境重启(environment = "stage" 或默认)
|
|
67
|
+
|
|
68
|
+
**集群名**: `optima-stage-cluster`
|
|
69
|
+
**服务名格式**: `{service}-stage`
|
|
70
|
+
|
|
71
|
+
**步骤**:
|
|
72
|
+
```bash
|
|
73
|
+
# 重启服务(强制重新部署)
|
|
74
|
+
aws ecs update-service \
|
|
75
|
+
--cluster optima-stage-cluster \
|
|
76
|
+
--service {service}-stage \
|
|
77
|
+
--force-new-deployment \
|
|
78
|
+
--region ap-southeast-1 \
|
|
79
|
+
--query 'service.{serviceName:serviceName,desiredCount:desiredCount,runningCount:runningCount,status:status}' \
|
|
80
|
+
--output table
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**可用服务**:
|
|
84
|
+
- `user-auth-stage`
|
|
85
|
+
- `user-auth-admin-stage`
|
|
86
|
+
- `commerce-backend-stage`
|
|
87
|
+
- `commerce-rq-worker-stage`
|
|
88
|
+
- `commerce-rq-scheduler-stage`
|
|
89
|
+
- `agentic-chat-stage`
|
|
90
|
+
- `session-gateway-stage`
|
|
91
|
+
- `bi-backend-stage`
|
|
92
|
+
- `bi-dashboard-stage`
|
|
93
|
+
- `optima-scout-stage`
|
|
94
|
+
- `ai-shell-web-ui-stage`
|
|
95
|
+
- `optima-store-stage`
|
|
96
|
+
- `pgbouncer-stage`
|
|
97
|
+
|
|
98
|
+
### 2. Prod 环境重启(environment = "prod")
|
|
99
|
+
|
|
100
|
+
**集群名**: `optima-prod-cluster`
|
|
101
|
+
**服务名格式**: `{service}-prod`
|
|
102
|
+
|
|
103
|
+
**⚠️ 安全提醒**: 重启 Prod 服务前,Claude 应主动向用户确认是否继续。
|
|
104
|
+
|
|
105
|
+
**步骤**:
|
|
106
|
+
```bash
|
|
107
|
+
# 重启服务(强制重新部署)
|
|
108
|
+
aws ecs update-service \
|
|
109
|
+
--cluster optima-prod-cluster \
|
|
110
|
+
--service {service}-prod \
|
|
111
|
+
--force-new-deployment \
|
|
112
|
+
--region ap-southeast-1 \
|
|
113
|
+
--query 'service.{serviceName:serviceName,desiredCount:desiredCount,runningCount:runningCount,status:status}' \
|
|
114
|
+
--output table
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**可用服务**:
|
|
118
|
+
- `user-auth-prod`
|
|
119
|
+
- `user-auth-admin-prod`
|
|
120
|
+
- `commerce-backend-prod`
|
|
121
|
+
- `commerce-rq-worker-prod`
|
|
122
|
+
- `commerce-rq-scheduler-prod`
|
|
123
|
+
- `agentic-chat-prod`
|
|
124
|
+
- `session-gateway-prod`
|
|
125
|
+
- `bi-backend-prod`
|
|
126
|
+
- `bi-dashboard-prod`
|
|
127
|
+
- `optima-scout-prod`
|
|
128
|
+
- `ai-shell-web-ui-prod`
|
|
129
|
+
|
|
130
|
+
**注意**: `optima-store` 和 `pgbouncer` 仅在 Stage 环境部署
|
|
131
|
+
|
|
132
|
+
## 查看重启进度
|
|
133
|
+
|
|
134
|
+
重启触发后,可以查看部署进度:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# 查看服务部署状态
|
|
138
|
+
aws ecs describe-services \
|
|
139
|
+
--cluster optima-{env}-cluster \
|
|
140
|
+
--services {service}-{env} \
|
|
141
|
+
--region ap-southeast-1 \
|
|
142
|
+
--query 'services[0].{serviceName:serviceName,status:status,runningCount:runningCount,desiredCount:desiredCount,deployments:deployments[*].{status:status,runningCount:runningCount,desiredCount:desiredCount}}' \
|
|
143
|
+
--output yaml
|
|
144
|
+
|
|
145
|
+
# 查看服务事件(最近的部署事件)
|
|
146
|
+
aws ecs describe-services \
|
|
147
|
+
--cluster optima-{env}-cluster \
|
|
148
|
+
--services {service}-{env} \
|
|
149
|
+
--region ap-southeast-1 \
|
|
150
|
+
--query 'services[0].events[:5]' \
|
|
151
|
+
--output table
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## 常见错误处理
|
|
155
|
+
|
|
156
|
+
### 错误:ServiceNotFoundException
|
|
157
|
+
|
|
158
|
+
**原因**: 服务名不存在
|
|
159
|
+
|
|
160
|
+
**解决**:
|
|
161
|
+
```bash
|
|
162
|
+
# 列出所有服务
|
|
163
|
+
aws ecs list-services --cluster optima-stage-cluster --region ap-southeast-1
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### 错误:ClusterNotFoundException
|
|
167
|
+
|
|
168
|
+
**原因**: 集群名错误
|
|
169
|
+
|
|
170
|
+
**解决**: 确认使用正确的集群名:
|
|
171
|
+
- Stage: `optima-stage-cluster`
|
|
172
|
+
- Prod: `optima-prod-cluster`
|
|
173
|
+
|
|
174
|
+
### 错误:AccessDeniedException
|
|
175
|
+
|
|
176
|
+
**原因**: AWS 凭证无权限
|
|
177
|
+
|
|
178
|
+
**解决**: 确认 AWS CLI 配置了正确的凭证,且有 ECS 操作权限
|
|
179
|
+
|
|
180
|
+
## 重启原理
|
|
181
|
+
|
|
182
|
+
`--force-new-deployment` 参数会:
|
|
183
|
+
1. 使用**当前**的 Task Definition(版本号不变)
|
|
184
|
+
2. 启动新的 Task 实例
|
|
185
|
+
3. 新 Task 健康检查通过后注册到 ALB
|
|
186
|
+
4. 旧 Task 优雅停止
|
|
187
|
+
|
|
188
|
+
这是一个零停机的滚动更新过程。
|
|
189
|
+
|
|
190
|
+
## 注意事项
|
|
191
|
+
|
|
192
|
+
1. **默认 Stage 环境**: 为避免误操作生产环境,默认重启 Stage
|
|
193
|
+
2. **Prod 需确认**: 重启 Prod 服务时 Claude 会主动确认
|
|
194
|
+
3. **版本不变**: 重启不会改变 Task Definition 版本号
|
|
195
|
+
4. **零停机**: ECS 会确保新 Task 健康后才停止旧 Task
|
|
196
|
+
5. **权限要求**: 需要 AWS CLI 配置了正确的凭证和 ECS 操作权限
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "restartEcs"
|
|
3
|
+
description: "当用户请求重启 ECS 服务、重启服务、restart service、重新部署服务、重启 session-gateway、重启 user-auth、重启后端服务时,使用此技能。支持 Stage、Prod 两个环境的 ECS 服务重启。"
|
|
4
|
+
allowed-tools: ["Bash"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 重启 ECS 服务
|
|
8
|
+
|
|
9
|
+
当你需要重启 ECS 集群中的服务时,使用这个场景。
|
|
10
|
+
|
|
11
|
+
## 适用情况
|
|
12
|
+
|
|
13
|
+
- 代码更新后需要使配置生效
|
|
14
|
+
- 服务异常需要快速恢复
|
|
15
|
+
- 服务状态异常,需要清理缓存或连接
|
|
16
|
+
- 内存泄漏等问题需要重启服务
|
|
17
|
+
|
|
18
|
+
## 快速操作
|
|
19
|
+
|
|
20
|
+
### 1. 重启 Stage 环境服务(默认,更安全)
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
/restart-ecs session-gateway
|
|
24
|
+
/restart-ecs user-auth
|
|
25
|
+
/restart-ecs commerce-backend
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**说明**:
|
|
29
|
+
- 默认重启 Stage 环境,避免误操作生产环境
|
|
30
|
+
- 使用 ECS `force-new-deployment` 实现零停机重启
|
|
31
|
+
- Task Definition 版本号不变
|
|
32
|
+
|
|
33
|
+
### 2. 重启 Prod 环境服务
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
/restart-ecs session-gateway prod
|
|
37
|
+
/restart-ecs user-auth prod
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**说明**:
|
|
41
|
+
- 重启生产环境服务
|
|
42
|
+
- Claude 会主动确认是否继续
|
|
43
|
+
- 同样是零停机滚动更新
|
|
44
|
+
|
|
45
|
+
### 3. 列出可用服务
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
/restart-ecs list # 列出 Stage 环境服务
|
|
49
|
+
/restart-ecs list prod # 列出 Prod 环境服务
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 环境信息
|
|
53
|
+
|
|
54
|
+
### Stage 环境
|
|
55
|
+
|
|
56
|
+
**集群名**: `optima-stage-cluster`
|
|
57
|
+
|
|
58
|
+
**可用服务**:
|
|
59
|
+
| 服务简称 | 完整服务名 | 说明 |
|
|
60
|
+
|---------|-----------|------|
|
|
61
|
+
| user-auth | user-auth-stage | 用户认证服务 |
|
|
62
|
+
| user-auth-admin | user-auth-admin-stage | 认证管理后台 |
|
|
63
|
+
| commerce-backend | commerce-backend-stage | 电商后端 API |
|
|
64
|
+
| commerce-rq-worker | commerce-rq-worker-stage | RQ 后台任务 |
|
|
65
|
+
| commerce-rq-scheduler | commerce-rq-scheduler-stage | RQ 定时调度 |
|
|
66
|
+
| agentic-chat | agentic-chat-stage | AI 聊天服务 |
|
|
67
|
+
| session-gateway | session-gateway-stage | AI Shell 网关 |
|
|
68
|
+
| bi-backend | bi-backend-stage | BI 后端 |
|
|
69
|
+
| bi-dashboard | bi-dashboard-stage | BI 仪表板 |
|
|
70
|
+
| optima-scout | optima-scout-stage | 产品研究工具 |
|
|
71
|
+
| ai-shell-web-ui | ai-shell-web-ui-stage | Shell Web UI |
|
|
72
|
+
| optima-store | optima-store-stage | 商城前端 |
|
|
73
|
+
| pgbouncer | pgbouncer-stage | 数据库连接池 |
|
|
74
|
+
|
|
75
|
+
### Prod 环境
|
|
76
|
+
|
|
77
|
+
**集群名**: `optima-prod-cluster`
|
|
78
|
+
|
|
79
|
+
**可用服务**:
|
|
80
|
+
| 服务简称 | 完整服务名 | 说明 |
|
|
81
|
+
|---------|-----------|------|
|
|
82
|
+
| user-auth | user-auth-prod | 用户认证服务 |
|
|
83
|
+
| user-auth-admin | user-auth-admin-prod | 认证管理后台 |
|
|
84
|
+
| commerce-backend | commerce-backend-prod | 电商后端 API |
|
|
85
|
+
| commerce-rq-worker | commerce-rq-worker-prod | RQ 后台任务 |
|
|
86
|
+
| commerce-rq-scheduler | commerce-rq-scheduler-prod | RQ 定时调度 |
|
|
87
|
+
| agentic-chat | agentic-chat-prod | AI 聊天服务 |
|
|
88
|
+
| session-gateway | session-gateway-prod | AI Shell 网关 |
|
|
89
|
+
| bi-backend | bi-backend-prod | BI 后端 |
|
|
90
|
+
| bi-dashboard | bi-dashboard-prod | BI 仪表板 |
|
|
91
|
+
| optima-scout | optima-scout-prod | 产品研究工具 |
|
|
92
|
+
| ai-shell-web-ui | ai-shell-web-ui-prod | Shell Web UI |
|
|
93
|
+
|
|
94
|
+
**注意**: `optima-store` 和 `pgbouncer` 仅在 Stage 环境部署
|
|
95
|
+
|
|
96
|
+
## 重启原理
|
|
97
|
+
|
|
98
|
+
ECS `--force-new-deployment` 的工作流程:
|
|
99
|
+
|
|
100
|
+
1. **启动新 Task** - 使用当前 Task Definition 创建新实例
|
|
101
|
+
2. **健康检查** - 新 Task 通过 ALB 健康检查
|
|
102
|
+
3. **注册到 ALB** - 新 Task 开始接收流量
|
|
103
|
+
4. **停止旧 Task** - 旧 Task 优雅停止
|
|
104
|
+
|
|
105
|
+
这是一个**零停机**的滚动更新过程,用户请求不会中断。
|
|
106
|
+
|
|
107
|
+
## 常见使用场景
|
|
108
|
+
|
|
109
|
+
### 场景 1:服务配置更新后重启
|
|
110
|
+
|
|
111
|
+
当修改了 Infisical 中的环境变量后,需要重启服务使配置生效:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
/restart-ecs commerce-backend stage
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 场景 2:服务异常恢复
|
|
118
|
+
|
|
119
|
+
服务出现内存泄漏或连接池耗尽等问题:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
/restart-ecs session-gateway prod
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### 场景 3:批量重启多个服务
|
|
126
|
+
|
|
127
|
+
需要重启多个相关服务:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
# 依次重启
|
|
131
|
+
/restart-ecs user-auth stage
|
|
132
|
+
/restart-ecs commerce-backend stage
|
|
133
|
+
/restart-ecs agentic-chat stage
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## 查看重启进度
|
|
137
|
+
|
|
138
|
+
重启触发后,可以查看部署状态:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# 查看服务部署状态
|
|
142
|
+
aws ecs describe-services \
|
|
143
|
+
--cluster optima-stage-cluster \
|
|
144
|
+
--services session-gateway-stage \
|
|
145
|
+
--region ap-southeast-1 \
|
|
146
|
+
--query 'services[0].deployments' \
|
|
147
|
+
--output table
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## 安全提醒
|
|
151
|
+
|
|
152
|
+
1. **Stage 优先**: 默认重启 Stage 环境,降低误操作风险
|
|
153
|
+
2. **Prod 确认**: 重启 Prod 服务前会主动确认
|
|
154
|
+
3. **版本不变**: 重启不会改变 Task Definition 版本号
|
|
155
|
+
4. **可恢复**: 如果新 Task 启动失败,旧 Task 会继续运行
|
|
156
|
+
|
|
157
|
+
## 相关命令
|
|
158
|
+
|
|
159
|
+
- `/restart-ecs` - 重启 ECS 服务(详细使用方法请查看 `/restart-ecs --help`)
|
|
160
|
+
- `/logs` - 查看服务日志,可用于确认重启后服务状态
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "show-env"
|
|
3
|
+
description: "当用户请求查看环境变量、查看配置、查看服务配置、环境变量是什么、env 变量、服务环境变量、查看 Infisical 配置时,使用此技能。支持查看当前 shell 环境变量,以及 Stage、Prod 环境的服务配置。"
|
|
4
|
+
allowed-tools: ["Bash", "SlashCommand"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 查看环境变量
|
|
8
|
+
|
|
9
|
+
当你需要查看环境变量或服务配置时,使用这个场景。
|
|
10
|
+
|
|
11
|
+
## 适用情况
|
|
12
|
+
|
|
13
|
+
- 查看当前 shell 的环境变量
|
|
14
|
+
- 查看服务的环境变量配置(从 Infisical)
|
|
15
|
+
- 排查环境配置问题
|
|
16
|
+
- 确认某个环境变量是否设置正确
|
|
17
|
+
- 对比不同环境的配置差异
|
|
18
|
+
|
|
19
|
+
## 快速操作
|
|
20
|
+
|
|
21
|
+
### 1. 查看当前 shell 环境变量
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# 查看所有环境变量
|
|
25
|
+
env
|
|
26
|
+
|
|
27
|
+
# 查看特定环境变量
|
|
28
|
+
echo $OPTIMA_TOKEN
|
|
29
|
+
echo $OPTIMA_ENV
|
|
30
|
+
|
|
31
|
+
# 搜索包含特定关键字的环境变量
|
|
32
|
+
env | grep -i optima
|
|
33
|
+
env | grep -i aws
|
|
34
|
+
env | grep -i database
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. 查看 Infisical 中的服务配置
|
|
38
|
+
|
|
39
|
+
使用 `optima-show-env` CLI 工具查看存储在 Infisical 中的服务配置:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# 查看 Stage 环境的 commerce-backend 配置
|
|
43
|
+
optima-show-env commerce-backend stage
|
|
44
|
+
|
|
45
|
+
# 查看 Prod 环境的 user-auth 配置
|
|
46
|
+
optima-show-env user-auth prod
|
|
47
|
+
|
|
48
|
+
# 查看 Stage 环境的 agentic-chat 配置
|
|
49
|
+
optima-show-env agentic-chat stage
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**支持的服务**:
|
|
53
|
+
- `commerce-backend` - 电商后端 API
|
|
54
|
+
- `user-auth` - 用户认证服务
|
|
55
|
+
- `agentic-chat` - AI 聊天服务
|
|
56
|
+
- `bi` - BI 后端
|
|
57
|
+
- `session-gateway` - AI Shell 网关
|
|
58
|
+
- `optima-store` - 商城前端
|
|
59
|
+
- `optima-scout` - 产品研究工具
|
|
60
|
+
- `mcp-host` - MCP 主机
|
|
61
|
+
|
|
62
|
+
**支持的环境**:
|
|
63
|
+
- `stage` - Stage 预发布环境
|
|
64
|
+
- `prod` - Prod 生产环境
|
|
65
|
+
|
|
66
|
+
### 3. 使用过滤和选项
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# 只查看数据库相关配置
|
|
70
|
+
optima-show-env commerce-backend stage --filter DATABASE
|
|
71
|
+
|
|
72
|
+
# 只查看 STRIPE 相关配置
|
|
73
|
+
optima-show-env commerce-backend stage --filter STRIPE
|
|
74
|
+
|
|
75
|
+
# 只显示变量名(不显示值)
|
|
76
|
+
optima-show-env user-auth prod --keys-only
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 常见场景
|
|
80
|
+
|
|
81
|
+
### 场景 1:确认环境变量是否设置
|
|
82
|
+
|
|
83
|
+
**用户请求**:"帮我看看 OPTIMA_TOKEN 环境变量设置了没有"
|
|
84
|
+
|
|
85
|
+
**步骤**:
|
|
86
|
+
```bash
|
|
87
|
+
# 检查是否设置
|
|
88
|
+
if [ -n "$OPTIMA_TOKEN" ]; then
|
|
89
|
+
echo "OPTIMA_TOKEN 已设置"
|
|
90
|
+
echo "长度: ${#OPTIMA_TOKEN} 字符"
|
|
91
|
+
else
|
|
92
|
+
echo "OPTIMA_TOKEN 未设置"
|
|
93
|
+
fi
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 场景 2:排查服务配置问题
|
|
97
|
+
|
|
98
|
+
**用户请求**:"commerce-backend 连接不上数据库,帮我看看配置"
|
|
99
|
+
|
|
100
|
+
**步骤**:
|
|
101
|
+
1. 查看数据库相关配置:
|
|
102
|
+
```bash
|
|
103
|
+
optima-show-env commerce-backend stage --filter DATABASE
|
|
104
|
+
```
|
|
105
|
+
2. 确认连接字符串格式
|
|
106
|
+
3. 检查密码是否包含特殊字符需要转义
|
|
107
|
+
|
|
108
|
+
### 场景 3:对比不同环境配置
|
|
109
|
+
|
|
110
|
+
**用户请求**:"对比一下 Stage 和 Prod 环境的配置差异"
|
|
111
|
+
|
|
112
|
+
**步骤**:
|
|
113
|
+
```bash
|
|
114
|
+
# 导出两个环境的配置(只看变量名)
|
|
115
|
+
optima-show-env commerce-backend stage --keys-only > /tmp/env-stage.txt
|
|
116
|
+
optima-show-env commerce-backend prod --keys-only > /tmp/env-prod.txt
|
|
117
|
+
|
|
118
|
+
# 对比差异
|
|
119
|
+
diff /tmp/env-stage.txt /tmp/env-prod.txt
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 场景 4:查看特定类型配置
|
|
123
|
+
|
|
124
|
+
**用户请求**:"帮我看看 Stripe 相关配置"
|
|
125
|
+
|
|
126
|
+
**步骤**:
|
|
127
|
+
```bash
|
|
128
|
+
optima-show-env commerce-backend stage --filter STRIPE
|
|
129
|
+
optima-show-env commerce-backend prod --filter STRIPE
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 环境变量分类
|
|
133
|
+
|
|
134
|
+
### 常见环境变量类型
|
|
135
|
+
|
|
136
|
+
| 类型 | 示例变量 | 说明 |
|
|
137
|
+
|------|----------|------|
|
|
138
|
+
| 数据库 | `DATABASE_URL`, `DB_HOST`, `DB_PASSWORD` | 数据库连接配置 |
|
|
139
|
+
| Redis | `REDIS_URL`, `REDIS_HOST`, `REDIS_DB` | 缓存配置 |
|
|
140
|
+
| AWS/S3 | `MINIO_ACCESS_KEY`, `MINIO_SECRET_KEY`, `MINIO_BUCKET` | 对象存储配置 |
|
|
141
|
+
| Auth | `JWT_SECRET_KEY`, `OAUTH_CLIENT_ID`, `SECRET_KEY` | 认证相关配置 |
|
|
142
|
+
| Stripe | `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET` | 支付配置 |
|
|
143
|
+
| 应用 | `DEBUG`, `LOG_LEVEL`, `NODE_ENV` | 应用运行配置 |
|
|
144
|
+
|
|
145
|
+
## CLI 选项说明
|
|
146
|
+
|
|
147
|
+
| 选项 | 说明 |
|
|
148
|
+
|------|------|
|
|
149
|
+
| `--filter <pattern>` | 按变量名过滤(不区分大小写) |
|
|
150
|
+
| `--keys-only` | 只显示变量名,不显示值 |
|
|
151
|
+
| `--help` | 显示帮助信息 |
|
|
152
|
+
|
|
153
|
+
## 故障排查
|
|
154
|
+
|
|
155
|
+
### 问题 1:optima-show-env 命令不存在
|
|
156
|
+
|
|
157
|
+
**解决方案**:
|
|
158
|
+
```bash
|
|
159
|
+
# 安装或更新工具
|
|
160
|
+
npm install -g @optima-chat/dev-skills@latest
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### 问题 2:无法访问 Infisical
|
|
164
|
+
|
|
165
|
+
**可能原因**:
|
|
166
|
+
- GitHub CLI 未登录
|
|
167
|
+
- 无权访问 Optima-Chat/optima-dev-skills 仓库的 Variables
|
|
168
|
+
|
|
169
|
+
**解决方案**:
|
|
170
|
+
- 运行 `gh auth login` 登录 GitHub
|
|
171
|
+
- 确认有仓库访问权限
|
|
172
|
+
|
|
173
|
+
### 问题 3:服务不存在
|
|
174
|
+
|
|
175
|
+
**错误信息**: "Unknown service 'xxx'"
|
|
176
|
+
|
|
177
|
+
**解决方案**:
|
|
178
|
+
- 检查服务名称拼写
|
|
179
|
+
- 运行 `optima-show-env --help` 查看支持的服务列表
|
|
180
|
+
|
|
181
|
+
## 相关命令
|
|
182
|
+
|
|
183
|
+
- `/show-env` - 查看环境变量
|
|
184
|
+
- `/logs` - 查看服务日志
|
|
185
|
+
- `/query-db` - 查询数据库
|
package/README.md
CHANGED
|
@@ -23,12 +23,13 @@ Optima Dev Skills 让 Claude Code 能够直接在 **CI、Stage、Prod** 三个
|
|
|
23
23
|
- **任务驱动** - 基于具体任务场景(查看日志、调用 API),不是抽象分类
|
|
24
24
|
- **跨环境协作** - 统一的命令在 CI、Stage、Prod 三个环境中使用
|
|
25
25
|
|
|
26
|
-
## 📋 任务场景(
|
|
26
|
+
## 📋 任务场景(6 个)
|
|
27
27
|
|
|
28
28
|
当 Claude Code 识别到以下任务时,会自动加载对应的 Skill:
|
|
29
29
|
|
|
30
30
|
- **logs** - 查看 CI/Stage/Prod 的服务器日志
|
|
31
31
|
- **query-db** - 查询 CI/Stage/Prod 的数据库
|
|
32
|
+
- **show-env** - 查看 Stage/Prod 的服务环境变量(从 Infisical)
|
|
32
33
|
- **generate-test-token** - 生成测试 Access Token 用于 API 测试
|
|
33
34
|
- **use-commerce-cli** - 使用 Commerce CLI 管理电商店铺
|
|
34
35
|
- **read-code** - 阅读 Optima-Chat 组织下任意仓库的代码
|
|
@@ -91,10 +92,12 @@ Claude:
|
|
|
91
92
|
| 工具 | 说明 | 示例 |
|
|
92
93
|
|------|------|------|
|
|
93
94
|
| `optima-query-db` | 数据库查询工具 | `optima-query-db user-auth "SELECT COUNT(*) FROM users" prod` |
|
|
95
|
+
| `optima-show-env` | 查看服务环境变量 | `optima-show-env commerce-backend stage --filter DATABASE` |
|
|
94
96
|
| `optima-generate-test-token` | 生成测试 token | `optima-generate-test-token --business-name "测试店铺"` |
|
|
95
97
|
|
|
96
98
|
**特点**:
|
|
97
99
|
- ✅ 支持 CI、Stage、Prod 三个环境(query-db)
|
|
100
|
+
- ✅ 支持 Stage、Prod 环境(show-env)
|
|
98
101
|
- ✅ 自动管理 SSH 隧道和密钥
|
|
99
102
|
- ✅ 可在任何终端直接使用
|
|
100
103
|
- ✅ 自动注册账户、获取 token、设置 merchant profile(generate-test-token)
|
|
@@ -114,6 +117,7 @@ optima-dev-skills/
|
|
|
114
117
|
│ └── skills/
|
|
115
118
|
│ ├── logs/ # 日志查看 skill
|
|
116
119
|
│ ├── query-db/ # 数据库查询 skill
|
|
120
|
+
│ ├── show-env/ # 环境变量查看 skill
|
|
117
121
|
│ ├── generate-test-token/ # 测试 token 生成 skill
|
|
118
122
|
│ ├── use-commerce-cli/ # Commerce CLI 使用 skill
|
|
119
123
|
│ └── read-code/ # 代码阅读 skill
|
|
@@ -121,6 +125,7 @@ optima-dev-skills/
|
|
|
121
125
|
├── bin/
|
|
122
126
|
│ └── helpers/
|
|
123
127
|
│ ├── query-db.ts # CLI: 数据库查询
|
|
128
|
+
│ ├── show-env.ts # CLI: 查看环境变量
|
|
124
129
|
│ └── generate-test-token.ts # CLI: 生成测试 token
|
|
125
130
|
│
|
|
126
131
|
└── docs/
|
|
@@ -228,16 +233,16 @@ $ optima-query-db commerce-backend "SELECT id, title FROM products LIMIT 5" stag
|
|
|
228
233
|
|
|
229
234
|
## 🛠️ 开发状态
|
|
230
235
|
|
|
231
|
-
**当前版本**: 0.7.
|
|
236
|
+
**当前版本**: 0.7.16
|
|
232
237
|
|
|
233
238
|
**已完成**:
|
|
234
239
|
- ✅ 4 个命令:`/logs`、`/query-db`、`/generate-test-token`、`/read-code`
|
|
235
|
-
- ✅
|
|
240
|
+
- ✅ 6 个任务场景:`logs`、`query-db`、`show-env`、`generate-test-token`、`use-commerce-cli`、`read-code`
|
|
236
241
|
- ✅ 支持 CI、Stage、Prod 三个环境
|
|
237
242
|
- ✅ CI 环境通过 SSH + Docker 访问
|
|
238
243
|
- ✅ Stage/Prod 通过 SSH 隧道访问 RDS
|
|
239
|
-
- ✅ TypeScript CLI 工具:`optima-query-db`、`optima-generate-test-token`
|
|
240
|
-
- ✅ 通过 Infisical
|
|
244
|
+
- ✅ TypeScript CLI 工具:`optima-query-db`、`optima-show-env`、`optima-generate-test-token`
|
|
245
|
+
- ✅ 通过 Infisical 动态获取密钥和环境变量
|
|
241
246
|
- ✅ 自动生成测试 token 并设置 merchant profile
|
|
242
247
|
- ✅ `generate-test-token` 支持 development 和 production 环境
|
|
243
248
|
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
|
|
5
|
+
interface InfisicalConfig {
|
|
6
|
+
url: string;
|
|
7
|
+
clientId: string;
|
|
8
|
+
clientSecret: string;
|
|
9
|
+
projectId: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// 支持的服务列表(Infisical 路径为 /services/<service-name>)
|
|
13
|
+
const SUPPORTED_SERVICES = [
|
|
14
|
+
'commerce-backend',
|
|
15
|
+
'user-auth',
|
|
16
|
+
'agentic-chat',
|
|
17
|
+
'bi',
|
|
18
|
+
'session-gateway',
|
|
19
|
+
'optima-store',
|
|
20
|
+
'optima-scout',
|
|
21
|
+
'mcp-host'
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
// 环境到 Infisical environment 的映射
|
|
25
|
+
const ENV_MAP: Record<string, string> = {
|
|
26
|
+
stage: 'staging',
|
|
27
|
+
prod: 'prod'
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function getGitHubVariable(name: string): string {
|
|
31
|
+
return execSync(`gh variable get ${name} -R Optima-Chat/optima-dev-skills`, { encoding: 'utf-8' }).trim();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function getInfisicalConfig(): InfisicalConfig {
|
|
35
|
+
return {
|
|
36
|
+
url: getGitHubVariable('INFISICAL_URL'),
|
|
37
|
+
clientId: getGitHubVariable('INFISICAL_CLIENT_ID'),
|
|
38
|
+
clientSecret: getGitHubVariable('INFISICAL_CLIENT_SECRET'),
|
|
39
|
+
projectId: getGitHubVariable('INFISICAL_PROJECT_ID')
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function getInfisicalToken(config: InfisicalConfig): string {
|
|
44
|
+
const response = execSync(
|
|
45
|
+
`curl -s -X POST "${config.url}/api/v1/auth/universal-auth/login" -H "Content-Type: application/json" -d '{"clientId": "${config.clientId}", "clientSecret": "${config.clientSecret}"}'`,
|
|
46
|
+
{ encoding: 'utf-8' }
|
|
47
|
+
);
|
|
48
|
+
return JSON.parse(response).accessToken;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function getInfisicalSecrets(config: InfisicalConfig, token: string, environment: string, secretPath: string): Record<string, string> {
|
|
52
|
+
const response = execSync(
|
|
53
|
+
`curl -s "${config.url}/api/v3/secrets/raw?workspaceId=${config.projectId}&environment=${environment}&secretPath=${encodeURIComponent(secretPath)}" -H "Authorization: Bearer ${token}"`,
|
|
54
|
+
{ encoding: 'utf-8' }
|
|
55
|
+
);
|
|
56
|
+
const data = JSON.parse(response);
|
|
57
|
+
const secrets: Record<string, string> = {};
|
|
58
|
+
for (const secret of data.secrets || []) {
|
|
59
|
+
secrets[secret.secretKey] = secret.secretValue;
|
|
60
|
+
}
|
|
61
|
+
return secrets;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
function printHelp() {
|
|
66
|
+
console.log(`
|
|
67
|
+
Usage: optima-show-env <service> <environment> [options]
|
|
68
|
+
|
|
69
|
+
Arguments:
|
|
70
|
+
service Service name (${SUPPORTED_SERVICES.join(', ')})
|
|
71
|
+
environment Environment (stage, prod)
|
|
72
|
+
|
|
73
|
+
Options:
|
|
74
|
+
--filter Filter by key pattern (e.g., --filter DATABASE)
|
|
75
|
+
--keys-only Show only key names, not values
|
|
76
|
+
--help Show this help message
|
|
77
|
+
|
|
78
|
+
Examples:
|
|
79
|
+
optima-show-env commerce-backend stage
|
|
80
|
+
optima-show-env user-auth prod --filter DATABASE
|
|
81
|
+
optima-show-env bi stage --keys-only
|
|
82
|
+
`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function main() {
|
|
86
|
+
const args = process.argv.slice(2);
|
|
87
|
+
|
|
88
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
89
|
+
printHelp();
|
|
90
|
+
process.exit(0);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 解析参数
|
|
94
|
+
const positionalArgs: string[] = [];
|
|
95
|
+
let filter = '';
|
|
96
|
+
let keysOnly = false;
|
|
97
|
+
|
|
98
|
+
for (let i = 0; i < args.length; i++) {
|
|
99
|
+
if (args[i] === '--filter' && args[i + 1]) {
|
|
100
|
+
filter = args[i + 1];
|
|
101
|
+
i++;
|
|
102
|
+
} else if (args[i] === '--keys-only') {
|
|
103
|
+
keysOnly = true;
|
|
104
|
+
} else if (!args[i].startsWith('-')) {
|
|
105
|
+
positionalArgs.push(args[i]);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (positionalArgs.length < 2) {
|
|
110
|
+
console.error('Error: Missing required arguments');
|
|
111
|
+
printHelp();
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const [service, environment] = positionalArgs;
|
|
116
|
+
|
|
117
|
+
// 验证服务
|
|
118
|
+
if (!SUPPORTED_SERVICES.includes(service)) {
|
|
119
|
+
console.error(`Error: Unknown service '${service}'`);
|
|
120
|
+
console.error('Available services:', SUPPORTED_SERVICES.join(', '));
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// 验证环境
|
|
125
|
+
if (!ENV_MAP[environment]) {
|
|
126
|
+
console.error(`Error: Unknown environment '${environment}'`);
|
|
127
|
+
console.error('Available environments: stage, prod');
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Infisical 路径为 /services/<service-name>
|
|
132
|
+
const secretPath = `/services/${service}`;
|
|
133
|
+
|
|
134
|
+
console.log(`\n🔍 Fetching environment variables for ${service} (${environment.toUpperCase()})...\n`);
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
const infisicalConfig = getInfisicalConfig();
|
|
138
|
+
console.log('✓ Loaded Infisical config from GitHub Variables');
|
|
139
|
+
|
|
140
|
+
const token = getInfisicalToken(infisicalConfig);
|
|
141
|
+
console.log('✓ Obtained Infisical access token');
|
|
142
|
+
|
|
143
|
+
const infisicalEnv = ENV_MAP[environment];
|
|
144
|
+
const secrets = getInfisicalSecrets(infisicalConfig, token, infisicalEnv, secretPath);
|
|
145
|
+
console.log(`✓ Retrieved secrets from Infisical (path: ${secretPath})\n`);
|
|
146
|
+
|
|
147
|
+
const keys = Object.keys(secrets).sort();
|
|
148
|
+
|
|
149
|
+
if (keys.length === 0) {
|
|
150
|
+
console.log('No environment variables found.');
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 过滤
|
|
155
|
+
const filteredKeys = filter
|
|
156
|
+
? keys.filter(key => key.toUpperCase().includes(filter.toUpperCase()))
|
|
157
|
+
: keys;
|
|
158
|
+
|
|
159
|
+
if (filteredKeys.length === 0) {
|
|
160
|
+
console.log(`No environment variables matching '${filter}' found.`);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
console.log(`📋 Environment Variables (${filteredKeys.length} items):\n`);
|
|
165
|
+
console.log('─'.repeat(60));
|
|
166
|
+
|
|
167
|
+
for (const key of filteredKeys) {
|
|
168
|
+
if (keysOnly) {
|
|
169
|
+
console.log(key);
|
|
170
|
+
} else {
|
|
171
|
+
console.log(`${key}=${secrets[key]}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
console.log('─'.repeat(60));
|
|
176
|
+
|
|
177
|
+
} catch (error: any) {
|
|
178
|
+
console.error('\n❌ Error:', error.message);
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
main();
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
// 支持的服务列表(Infisical 路径为 /services/<service-name>)
|
|
6
|
+
const SUPPORTED_SERVICES = [
|
|
7
|
+
'commerce-backend',
|
|
8
|
+
'user-auth',
|
|
9
|
+
'agentic-chat',
|
|
10
|
+
'bi',
|
|
11
|
+
'session-gateway',
|
|
12
|
+
'optima-store',
|
|
13
|
+
'optima-scout',
|
|
14
|
+
'mcp-host'
|
|
15
|
+
];
|
|
16
|
+
// 环境到 Infisical environment 的映射
|
|
17
|
+
const ENV_MAP = {
|
|
18
|
+
stage: 'staging',
|
|
19
|
+
prod: 'prod'
|
|
20
|
+
};
|
|
21
|
+
function getGitHubVariable(name) {
|
|
22
|
+
return (0, child_process_1.execSync)(`gh variable get ${name} -R Optima-Chat/optima-dev-skills`, { encoding: 'utf-8' }).trim();
|
|
23
|
+
}
|
|
24
|
+
function getInfisicalConfig() {
|
|
25
|
+
return {
|
|
26
|
+
url: getGitHubVariable('INFISICAL_URL'),
|
|
27
|
+
clientId: getGitHubVariable('INFISICAL_CLIENT_ID'),
|
|
28
|
+
clientSecret: getGitHubVariable('INFISICAL_CLIENT_SECRET'),
|
|
29
|
+
projectId: getGitHubVariable('INFISICAL_PROJECT_ID')
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function getInfisicalToken(config) {
|
|
33
|
+
const response = (0, child_process_1.execSync)(`curl -s -X POST "${config.url}/api/v1/auth/universal-auth/login" -H "Content-Type: application/json" -d '{"clientId": "${config.clientId}", "clientSecret": "${config.clientSecret}"}'`, { encoding: 'utf-8' });
|
|
34
|
+
return JSON.parse(response).accessToken;
|
|
35
|
+
}
|
|
36
|
+
function getInfisicalSecrets(config, token, environment, secretPath) {
|
|
37
|
+
const response = (0, child_process_1.execSync)(`curl -s "${config.url}/api/v3/secrets/raw?workspaceId=${config.projectId}&environment=${environment}&secretPath=${encodeURIComponent(secretPath)}" -H "Authorization: Bearer ${token}"`, { encoding: 'utf-8' });
|
|
38
|
+
const data = JSON.parse(response);
|
|
39
|
+
const secrets = {};
|
|
40
|
+
for (const secret of data.secrets || []) {
|
|
41
|
+
secrets[secret.secretKey] = secret.secretValue;
|
|
42
|
+
}
|
|
43
|
+
return secrets;
|
|
44
|
+
}
|
|
45
|
+
function printHelp() {
|
|
46
|
+
console.log(`
|
|
47
|
+
Usage: optima-show-env <service> <environment> [options]
|
|
48
|
+
|
|
49
|
+
Arguments:
|
|
50
|
+
service Service name (${SUPPORTED_SERVICES.join(', ')})
|
|
51
|
+
environment Environment (stage, prod)
|
|
52
|
+
|
|
53
|
+
Options:
|
|
54
|
+
--filter Filter by key pattern (e.g., --filter DATABASE)
|
|
55
|
+
--keys-only Show only key names, not values
|
|
56
|
+
--help Show this help message
|
|
57
|
+
|
|
58
|
+
Examples:
|
|
59
|
+
optima-show-env commerce-backend stage
|
|
60
|
+
optima-show-env user-auth prod --filter DATABASE
|
|
61
|
+
optima-show-env bi stage --keys-only
|
|
62
|
+
`);
|
|
63
|
+
}
|
|
64
|
+
async function main() {
|
|
65
|
+
const args = process.argv.slice(2);
|
|
66
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
67
|
+
printHelp();
|
|
68
|
+
process.exit(0);
|
|
69
|
+
}
|
|
70
|
+
// 解析参数
|
|
71
|
+
const positionalArgs = [];
|
|
72
|
+
let filter = '';
|
|
73
|
+
let keysOnly = false;
|
|
74
|
+
for (let i = 0; i < args.length; i++) {
|
|
75
|
+
if (args[i] === '--filter' && args[i + 1]) {
|
|
76
|
+
filter = args[i + 1];
|
|
77
|
+
i++;
|
|
78
|
+
}
|
|
79
|
+
else if (args[i] === '--keys-only') {
|
|
80
|
+
keysOnly = true;
|
|
81
|
+
}
|
|
82
|
+
else if (!args[i].startsWith('-')) {
|
|
83
|
+
positionalArgs.push(args[i]);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (positionalArgs.length < 2) {
|
|
87
|
+
console.error('Error: Missing required arguments');
|
|
88
|
+
printHelp();
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
const [service, environment] = positionalArgs;
|
|
92
|
+
// 验证服务
|
|
93
|
+
if (!SUPPORTED_SERVICES.includes(service)) {
|
|
94
|
+
console.error(`Error: Unknown service '${service}'`);
|
|
95
|
+
console.error('Available services:', SUPPORTED_SERVICES.join(', '));
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
// 验证环境
|
|
99
|
+
if (!ENV_MAP[environment]) {
|
|
100
|
+
console.error(`Error: Unknown environment '${environment}'`);
|
|
101
|
+
console.error('Available environments: stage, prod');
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
// Infisical 路径为 /services/<service-name>
|
|
105
|
+
const secretPath = `/services/${service}`;
|
|
106
|
+
console.log(`\n🔍 Fetching environment variables for ${service} (${environment.toUpperCase()})...\n`);
|
|
107
|
+
try {
|
|
108
|
+
const infisicalConfig = getInfisicalConfig();
|
|
109
|
+
console.log('✓ Loaded Infisical config from GitHub Variables');
|
|
110
|
+
const token = getInfisicalToken(infisicalConfig);
|
|
111
|
+
console.log('✓ Obtained Infisical access token');
|
|
112
|
+
const infisicalEnv = ENV_MAP[environment];
|
|
113
|
+
const secrets = getInfisicalSecrets(infisicalConfig, token, infisicalEnv, secretPath);
|
|
114
|
+
console.log(`✓ Retrieved secrets from Infisical (path: ${secretPath})\n`);
|
|
115
|
+
const keys = Object.keys(secrets).sort();
|
|
116
|
+
if (keys.length === 0) {
|
|
117
|
+
console.log('No environment variables found.');
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
// 过滤
|
|
121
|
+
const filteredKeys = filter
|
|
122
|
+
? keys.filter(key => key.toUpperCase().includes(filter.toUpperCase()))
|
|
123
|
+
: keys;
|
|
124
|
+
if (filteredKeys.length === 0) {
|
|
125
|
+
console.log(`No environment variables matching '${filter}' found.`);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
console.log(`📋 Environment Variables (${filteredKeys.length} items):\n`);
|
|
129
|
+
console.log('─'.repeat(60));
|
|
130
|
+
for (const key of filteredKeys) {
|
|
131
|
+
if (keysOnly) {
|
|
132
|
+
console.log(key);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
console.log(`${key}=${secrets[key]}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
console.log('─'.repeat(60));
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
console.error('\n❌ Error:', error.message);
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
main();
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optima-chat/dev-skills",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.17",
|
|
4
4
|
"description": "Claude Code Skills for Optima development team - cross-environment collaboration tools",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"optima-dev-skills": "./bin/cli.js",
|
|
8
8
|
"optima-query-db": "./dist/bin/helpers/query-db.js",
|
|
9
|
-
"optima-generate-test-token": "./dist/bin/helpers/generate-test-token.js"
|
|
9
|
+
"optima-generate-test-token": "./dist/bin/helpers/generate-test-token.js",
|
|
10
|
+
"optima-show-env": "./dist/bin/helpers/show-env.js"
|
|
10
11
|
},
|
|
11
12
|
"scripts": {
|
|
12
13
|
"postinstall": "node scripts/install.js",
|