speccore 8.3.290 → 8.3.296
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.en.md +16 -3
- package/README.md +9 -7
- package/dist/cli.js +11 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/about.d.ts.map +1 -1
- package/dist/commands/about.js +5 -0
- package/dist/commands/about.js.map +1 -1
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +77 -5
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/ask.js +2 -2
- package/dist/commands/ask.js.map +1 -1
- package/dist/commands/execute.js +1 -0
- package/dist/commands/execute.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +25 -4
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/iteration/taskify.d.ts.map +1 -1
- package/dist/commands/iteration/taskify.js +132 -7
- package/dist/commands/iteration/taskify.js.map +1 -1
- package/dist/commands/status-panel.d.ts +1 -0
- package/dist/commands/status-panel.d.ts.map +1 -1
- package/dist/commands/status-panel.js +65 -17
- package/dist/commands/status-panel.js.map +1 -1
- package/dist/commands/update-env-configs.d.ts.map +1 -1
- package/dist/commands/update-env-configs.js +6 -0
- package/dist/commands/update-env-configs.js.map +1 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +78 -1
- package/dist/commands/verify.js.map +1 -1
- package/dist/core/deploy/engine.d.ts +11 -0
- package/dist/core/deploy/engine.d.ts.map +1 -1
- package/dist/core/deploy/engine.js +35 -7
- package/dist/core/deploy/engine.js.map +1 -1
- package/dist/core/git-integration.d.ts +2 -1
- package/dist/core/git-integration.d.ts.map +1 -1
- package/dist/core/git-integration.js +38 -14
- package/dist/core/git-integration.js.map +1 -1
- package/dist/core/global-counters.d.ts +3 -0
- package/dist/core/global-counters.d.ts.map +1 -1
- package/dist/core/global-counters.js +3 -1
- package/dist/core/global-counters.js.map +1 -1
- package/dist/core/prompt-builder.d.ts.map +1 -1
- package/dist/core/prompt-builder.js +7 -6
- package/dist/core/prompt-builder.js.map +1 -1
- package/dist/core/spec-paths.d.ts.map +1 -1
- package/dist/core/spec-paths.js +3 -0
- package/dist/core/spec-paths.js.map +1 -1
- package/dist/core/spec-skeleton.d.ts.map +1 -1
- package/dist/core/spec-skeleton.js +6 -2
- package/dist/core/spec-skeleton.js.map +1 -1
- package/dist/core/state.d.ts +11 -0
- package/dist/core/state.d.ts.map +1 -1
- package/dist/core/state.js +33 -2
- package/dist/core/state.js.map +1 -1
- package/dist/core/ui-verify/index.d.ts +2 -2
- package/dist/core/ui-verify/index.d.ts.map +1 -1
- package/dist/core/ui-verify/index.js +3 -1
- package/dist/core/ui-verify/index.js.map +1 -1
- package/dist/core/ui-verify/smoke-engine.d.ts.map +1 -1
- package/dist/core/ui-verify/smoke-engine.js +36 -0
- package/dist/core/ui-verify/smoke-engine.js.map +1 -1
- package/dist/core/ui-verify/spec-generator.d.ts +32 -1
- package/dist/core/ui-verify/spec-generator.d.ts.map +1 -1
- package/dist/core/ui-verify/spec-generator.js +205 -21
- package/dist/core/ui-verify/spec-generator.js.map +1 -1
- package/dist/core/ui-verify/types.d.ts +2 -0
- package/dist/core/ui-verify/types.d.ts.map +1 -1
- package/package.json +3 -2
- package/templates/api-design-example.md +338 -0
- package/templates/ci/github-actions.yml +44 -0
- package/templates/database-example.md +223 -0
- package/templates/deploy-docker/README.md +296 -0
- package/templates/deploy-docker/backend-node.Dockerfile +52 -0
- package/templates/deploy-docker/deploy-remote.sh +79 -0
- package/templates/deploy-docker/docker-compose.yml +113 -0
- package/templates/deploy-docker/frontend.Dockerfile +43 -0
- package/templates/deploy-docker/nginx.conf +30 -0
- package/templates/deploy-examples.yaml +511 -0
- package/templates/deploy-java/Dockerfile +50 -0
- package/templates/deploy-java/README.md +212 -0
- package/templates/deploy-java/deploy.sh +120 -0
- package/templates/deploy-java/spring-boot.service +35 -0
- package/templates/deploy-nginx/README.md +59 -0
- package/templates/deploy-nginx/nginx-site.conf +103 -0
- package/templates/deploy-scripts/README.md +61 -0
- package/templates/deploy-scripts/deploy-compose.sh +19 -0
- package/templates/deploy-scripts/deploy-ftp.sh +28 -0
- package/templates/deploy-scripts/deploy-password-ssh.sh +26 -0
- package/templates/deploy-scripts/deploy-python.sh +30 -0
- package/templates/deploy-scripts/trigger-jenkins.sh +30 -0
- package/templates/html/speccore-ask-explain.html +10 -0
- package/templates/html/speccore-ask-guide.html +10 -0
- package/templates/html/speccore-ask-match.html +10 -0
- package/templates/html/speccore-ask-pipeline.html +1 -0
- package/templates/html/speccore-ask-result.html +10 -0
- package/templates/html/speccore-help.html +241 -0
- package/templates/html/speccore-setup-guide.html +289 -0
- package/templates/security-example.md +226 -0
- package/templates/speccore-yml-example.yml +222 -0
- package/templates/verify-spec-example.yaml +142 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# Java 后端部署指南
|
|
2
|
+
|
|
3
|
+
> 本目录提供 Java(Spring Boot)后端服务的部署模板和示例脚本。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 目录结构
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
deploy-java/
|
|
11
|
+
├── spring-boot.service # systemd service 文件模板
|
|
12
|
+
├── deploy.sh # 服务器端部署脚本(备份 → 替换 → 重启 → 健康检查)
|
|
13
|
+
├── Dockerfile # 多阶段构建 Dockerfile 示例
|
|
14
|
+
└── README.md # 本文件
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 部署方式一:systemd + SSH(推荐测试环境)
|
|
20
|
+
|
|
21
|
+
### 1. 服务器端准备(只需一次)
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# 创建部署目录
|
|
25
|
+
sudo mkdir -p /opt/services/order-service
|
|
26
|
+
sudo mkdir -p /var/log/order-service
|
|
27
|
+
|
|
28
|
+
# 复制 service 文件(将 spring-boot.service 中的占位符替换后复制)
|
|
29
|
+
# 注意:文件名必须与 PROJECT.yaml 中的 platform.name 一致
|
|
30
|
+
sudo cp spring-boot.service /etc/systemd/system/order-service.service
|
|
31
|
+
|
|
32
|
+
# 重载 systemd
|
|
33
|
+
sudo systemctl daemon-reload
|
|
34
|
+
sudo systemctl enable order-service
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. 替换 service 文件中的占位符
|
|
38
|
+
|
|
39
|
+
| 占位符 | 示例值 | 说明 |
|
|
40
|
+
|--------|--------|------|
|
|
41
|
+
| `{{APP_NAME}}` | `order-service` | 应用名,与 platform.name 一致 |
|
|
42
|
+
| `{{DEPLOY_USER}}` | `deployer` | 运行服务的系统用户 |
|
|
43
|
+
| `{{DEPLOY_DIR}}` | `/opt/services/order-service` | jar 文件所在目录 |
|
|
44
|
+
| `{{PROFILE}}` | `staging` | Spring Boot profile |
|
|
45
|
+
| `{{JVM_XMS}}` | `512m` | JVM 初始堆内存 |
|
|
46
|
+
| `{{JVM_XMX}}` | `1024m` | JVM 最大堆内存 |
|
|
47
|
+
|
|
48
|
+
### 3. PROJECT.yaml 配置
|
|
49
|
+
|
|
50
|
+
```yaml
|
|
51
|
+
platforms:
|
|
52
|
+
- name: order-service
|
|
53
|
+
type: backend
|
|
54
|
+
code_path: ./order-service
|
|
55
|
+
default_branch: main
|
|
56
|
+
deploy:
|
|
57
|
+
staging:
|
|
58
|
+
type: ssh
|
|
59
|
+
build_cmd: mvn clean package -DskipTests -P staging
|
|
60
|
+
output_dir: target
|
|
61
|
+
host: deployer@staging-server.example.com:22
|
|
62
|
+
key: ~/.ssh/id_rsa
|
|
63
|
+
remote_dir: /opt/services/order-service
|
|
64
|
+
script: sudo systemctl restart order-service
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 4. 数据库 / Redis 配置切换
|
|
68
|
+
|
|
69
|
+
**方式 A:Spring Boot Profiles(推荐)**
|
|
70
|
+
|
|
71
|
+
```yaml
|
|
72
|
+
# src/main/resources/application-staging.yml
|
|
73
|
+
spring:
|
|
74
|
+
datasource:
|
|
75
|
+
url: jdbc:mysql://staging-db:3306/order_db
|
|
76
|
+
username: ${DB_USER}
|
|
77
|
+
password: ${DB_PASS}
|
|
78
|
+
data:
|
|
79
|
+
redis:
|
|
80
|
+
host: staging-redis
|
|
81
|
+
port: 6379
|
|
82
|
+
password: ${REDIS_PASS}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**方式 B:环境变量注入(配合 systemd)**
|
|
86
|
+
|
|
87
|
+
在 `spring-boot.service` 的 `[Service]` 段增加:
|
|
88
|
+
```ini
|
|
89
|
+
Environment="DB_USER=order_user"
|
|
90
|
+
Environment="DB_PASS=secret"
|
|
91
|
+
Environment="REDIS_PASS=redis_secret"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
在 `application.yml` 中引用:
|
|
95
|
+
```yaml
|
|
96
|
+
spring:
|
|
97
|
+
datasource:
|
|
98
|
+
username: ${DB_USER}
|
|
99
|
+
password: ${DB_PASS}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### 5. 部署流程
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
speccore deploy --env staging --platform order-service
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
执行流程:
|
|
109
|
+
1. 本地执行 `mvn clean package -DskipTests -P staging`
|
|
110
|
+
2. SCP 上传 `target/*.jar` 到服务器 `/opt/services/order-service/`
|
|
111
|
+
3. SSH 执行 `sudo systemctl restart order-service`
|
|
112
|
+
4. systemd 自动完成:停止旧进程 → 启动新 jar → 写入日志
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 部署方式二:Docker(推荐生产环境)
|
|
117
|
+
|
|
118
|
+
### 1. 准备 Dockerfile
|
|
119
|
+
|
|
120
|
+
将 `Dockerfile` 复制到 Java 工程根目录(与 `pom.xml` 同级)。
|
|
121
|
+
|
|
122
|
+
### 2. PROJECT.yaml 配置
|
|
123
|
+
|
|
124
|
+
```yaml
|
|
125
|
+
platforms:
|
|
126
|
+
- name: order-service
|
|
127
|
+
type: backend
|
|
128
|
+
code_path: ./order-service
|
|
129
|
+
default_branch: main
|
|
130
|
+
deploy:
|
|
131
|
+
production:
|
|
132
|
+
type: docker
|
|
133
|
+
dockerfile: ./Dockerfile
|
|
134
|
+
registry: registry.example.com
|
|
135
|
+
image: my-project/order-service
|
|
136
|
+
tag: production
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### 3. 部署流程
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
speccore deploy --env production --platform order-service
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
执行流程:
|
|
146
|
+
1. 本地 `docker build`
|
|
147
|
+
2. 推送到镜像仓库 `registry.example.com/my-project/order-service:production`
|
|
148
|
+
3. 服务器端拉取镜像并运行(需配合额外的部署脚本或 CI/CD)
|
|
149
|
+
|
|
150
|
+
> 提示:如果服务器需要 SSH 登录后执行 `docker pull && docker run`,可将 deploy 类型改为 `script`,编写自定义脚本。
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 部署方式三:自定义脚本(最灵活)
|
|
155
|
+
|
|
156
|
+
如果 systemd 和 Docker 都不满足需求,使用 `script` 类型:
|
|
157
|
+
|
|
158
|
+
```yaml
|
|
159
|
+
deploy:
|
|
160
|
+
staging:
|
|
161
|
+
type: script
|
|
162
|
+
build_cmd: mvn clean package -DskipTests
|
|
163
|
+
script: ./scripts/deploy-custom.sh
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 数据库 / Redis 连接检查清单
|
|
169
|
+
|
|
170
|
+
| 检查项 | 说明 |
|
|
171
|
+
|--------|------|
|
|
172
|
+
| 网络连通性 | 服务器能否 ping 通数据库和 Redis 主机 |
|
|
173
|
+
| 防火墙 / 安全组 | 数据库端口(3306/5432)和 Redis 端口(6379)是否开放 |
|
|
174
|
+
| 用户名密码 | 确认 staging / production 环境的凭据正确 |
|
|
175
|
+
| 数据库存在性 | 目标数据库是否已创建 |
|
|
176
|
+
| 连接池配置 | HikariCP 的最大连接数是否超过数据库限制 |
|
|
177
|
+
| 时区 | JVM 时区、数据库时区、应用时区是否一致 |
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 常见问题
|
|
182
|
+
|
|
183
|
+
**Q: 部署后服务起不来,怎么排查?**
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# 查看服务状态
|
|
187
|
+
sudo systemctl status order-service --no-pager
|
|
188
|
+
|
|
189
|
+
# 查看日志
|
|
190
|
+
sudo journalctl -u order-service -f
|
|
191
|
+
|
|
192
|
+
# 查看应用日志
|
|
193
|
+
tail -f /var/log/order-service/app.log
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Q: 如何回滚到上一个版本?**
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
cd /opt/services/order-service
|
|
200
|
+
# 找到最新备份
|
|
201
|
+
LATEST=$(ls -t backups/*.jar | head -1)
|
|
202
|
+
cp "$LATEST" order-service.jar
|
|
203
|
+
sudo systemctl restart order-service
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Q: 多个环境(staging / production)如何管理配置?**
|
|
207
|
+
|
|
208
|
+
使用 Spring Boot profiles:
|
|
209
|
+
- `application-staging.yml` — 测试环境
|
|
210
|
+
- `application-production.yml` — 生产环境
|
|
211
|
+
- 打包时激活 profile:`-P staging`
|
|
212
|
+
- 运行时激活 profile:`--spring.profiles.active=staging`
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ═══════════════════════════════════════════════════════════
|
|
3
|
+
# Java 后端部署脚本(服务器端执行)
|
|
4
|
+
# ═══════════════════════════════════════════════════════════
|
|
5
|
+
#
|
|
6
|
+
# 用法:
|
|
7
|
+
# ./deploy.sh <app-name> [profile]
|
|
8
|
+
#
|
|
9
|
+
# 示例:
|
|
10
|
+
# ./deploy.sh order-service staging
|
|
11
|
+
# ./deploy.sh order-service production
|
|
12
|
+
#
|
|
13
|
+
# 该脚本由 speccore deploy 通过 SSH 调用,也可手动在服务器上执行。
|
|
14
|
+
# 功能:备份旧 jar → 替换新 jar → 重启 systemd 服务 → 健康检查
|
|
15
|
+
# ═══════════════════════════════════════════════════════════
|
|
16
|
+
|
|
17
|
+
set -euo pipefail
|
|
18
|
+
|
|
19
|
+
APP_NAME="${1:-}"
|
|
20
|
+
PROFILE="${2:-staging}"
|
|
21
|
+
|
|
22
|
+
if [ -z "$APP_NAME" ]; then
|
|
23
|
+
echo "用法: $0 <app-name> [profile]"
|
|
24
|
+
echo "示例: $0 order-service staging"
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
DEPLOY_DIR="/opt/services/$APP_NAME"
|
|
29
|
+
BACKUP_DIR="$DEPLOY_DIR/backups"
|
|
30
|
+
LOG_DIR="/var/log/$APP_NAME"
|
|
31
|
+
JAR_FILE="$DEPLOY_DIR/$APP_NAME.jar"
|
|
32
|
+
NEW_JAR="$DEPLOY_DIR/$APP_NAME-new.jar"
|
|
33
|
+
HEALTH_URL="http://localhost:8080/actuator/health" # 根据实际端口和路径修改
|
|
34
|
+
|
|
35
|
+
echo "========================================"
|
|
36
|
+
echo "部署应用: $APP_NAME"
|
|
37
|
+
echo "环境: $PROFILE"
|
|
38
|
+
echo "========================================"
|
|
39
|
+
|
|
40
|
+
# ── 1. 预检 ──
|
|
41
|
+
if [ ! -f "$NEW_JAR" ]; then
|
|
42
|
+
echo "❌ 错误:未找到新 jar 文件: $NEW_JAR"
|
|
43
|
+
echo " 请确保 speccore deploy 已成功上传 jar 到该路径"
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# ── 2. 创建必要目录 ──
|
|
48
|
+
mkdir -p "$BACKUP_DIR" "$LOG_DIR"
|
|
49
|
+
|
|
50
|
+
# ── 3. 备份旧版本 ──
|
|
51
|
+
if [ -f "$JAR_FILE" ]; then
|
|
52
|
+
BACKUP_NAME="$BACKUP_DIR/$APP_NAME-$(date +%Y%m%d-%H%M%S).jar"
|
|
53
|
+
cp "$JAR_FILE" "$BACKUP_NAME"
|
|
54
|
+
echo "✅ 旧版本已备份: $BACKUP_NAME"
|
|
55
|
+
|
|
56
|
+
# 只保留最近 5 个备份
|
|
57
|
+
ls -t "$BACKUP_DIR"/*.jar 2>/dev/null | tail -n +6 | xargs -r rm -f
|
|
58
|
+
echo "🧹 已清理旧备份(保留最近 5 个)"
|
|
59
|
+
else
|
|
60
|
+
echo "ℹ️ 首次部署,无旧版本需要备份"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# ── 4. 替换 jar ──
|
|
64
|
+
mv "$NEW_JAR" "$JAR_FILE"
|
|
65
|
+
echo "✅ 已替换 jar: $JAR_FILE"
|
|
66
|
+
|
|
67
|
+
# ── 5. 确保 systemd service 文件存在 ──
|
|
68
|
+
SERVICE_FILE="/etc/systemd/system/$APP_NAME.service"
|
|
69
|
+
if [ ! -f "$SERVICE_FILE" ]; then
|
|
70
|
+
echo "⚠️ 警告:systemd service 文件不存在: $SERVICE_FILE"
|
|
71
|
+
echo " 请从 templates/deploy-java/spring-boot.service 复制并修改后部署到该路径"
|
|
72
|
+
echo " 然后执行: sudo systemctl daemon-reload && sudo systemctl enable $APP_NAME"
|
|
73
|
+
exit 1
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# ── 6. 重启服务 ──
|
|
77
|
+
echo "🔄 重启服务..."
|
|
78
|
+
sudo systemctl daemon-reload
|
|
79
|
+
sudo systemctl restart "$APP_NAME"
|
|
80
|
+
|
|
81
|
+
# ── 7. 等待启动 ──
|
|
82
|
+
echo "⏳ 等待服务启动(最多 30 秒)..."
|
|
83
|
+
for i in {1..30}; do
|
|
84
|
+
sleep 1
|
|
85
|
+
if systemctl is-active --quiet "$APP_NAME"; then
|
|
86
|
+
echo "✅ 服务已启动"
|
|
87
|
+
break
|
|
88
|
+
fi
|
|
89
|
+
if [ "$i" -eq 30 ]; then
|
|
90
|
+
echo "❌ 服务启动超时"
|
|
91
|
+
echo "📋 日志 tail -n 50:"
|
|
92
|
+
sudo journalctl -u "$APP_NAME" --no-pager -n 50 || true
|
|
93
|
+
exit 1
|
|
94
|
+
fi
|
|
95
|
+
done
|
|
96
|
+
|
|
97
|
+
# ── 8. 健康检查 ──
|
|
98
|
+
echo "🏥 执行健康检查..."
|
|
99
|
+
for i in {1..10}; do
|
|
100
|
+
sleep 2
|
|
101
|
+
if curl -sf "$HEALTH_URL" >/dev/null 2>&1; then
|
|
102
|
+
echo "✅ 健康检查通过: $HEALTH_URL"
|
|
103
|
+
break
|
|
104
|
+
fi
|
|
105
|
+
if [ "$i" -eq 10 ]; then
|
|
106
|
+
echo "⚠️ 健康检查未通过,但服务已启动"
|
|
107
|
+
echo " 请手动检查: curl $HEALTH_URL"
|
|
108
|
+
fi
|
|
109
|
+
done
|
|
110
|
+
|
|
111
|
+
# ── 9. 显示状态 ──
|
|
112
|
+
echo ""
|
|
113
|
+
echo "========================================"
|
|
114
|
+
echo "📋 部署完成"
|
|
115
|
+
echo "========================================"
|
|
116
|
+
sudo systemctl status "$APP_NAME" --no-pager || true
|
|
117
|
+
echo ""
|
|
118
|
+
echo "日志查看:"
|
|
119
|
+
echo " journalctl -u $APP_NAME -f"
|
|
120
|
+
echo " tail -f $LOG_DIR/app.log"
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[Unit]
|
|
2
|
+
Description={{APP_NAME}}
|
|
3
|
+
After=network.target
|
|
4
|
+
|
|
5
|
+
[Service]
|
|
6
|
+
Type=simple
|
|
7
|
+
User={{DEPLOY_USER}}
|
|
8
|
+
Group={{DEPLOY_USER}}
|
|
9
|
+
WorkingDirectory={{DEPLOY_DIR}}
|
|
10
|
+
|
|
11
|
+
# Spring Boot Profile(按环境切换:staging / production / test)
|
|
12
|
+
Environment="SPRING_PROFILES_ACTIVE={{PROFILE}}"
|
|
13
|
+
|
|
14
|
+
# JVM 参数
|
|
15
|
+
Environment="JAVA_OPTS=-Xms{{JVM_XMS}} -Xmx{{JVM_XMX}} -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom"
|
|
16
|
+
|
|
17
|
+
# 启动命令
|
|
18
|
+
ExecStart=/usr/bin/java $JAVA_OPTS -jar {{APP_NAME}}.jar
|
|
19
|
+
|
|
20
|
+
# 优雅停止(SIGTERM 触发 Spring Boot 的 shutdown hook)
|
|
21
|
+
ExecStop=/bin/kill -SIGTERM $MAINPID
|
|
22
|
+
|
|
23
|
+
# 进程管理
|
|
24
|
+
Restart=on-failure
|
|
25
|
+
RestartSec=10
|
|
26
|
+
StartLimitInterval=60s
|
|
27
|
+
StartLimitBurst=3
|
|
28
|
+
|
|
29
|
+
# 日志输出(systemd 240+ 支持 append 模式)
|
|
30
|
+
# 旧版本 systemd 可改用:StandardOutput=file:/var/log/{{APP_NAME}}/app.log
|
|
31
|
+
StandardOutput=append:/var/log/{{APP_NAME}}/app.log
|
|
32
|
+
StandardError=append:/var/log/{{APP_NAME}}/error.log
|
|
33
|
+
|
|
34
|
+
[Install]
|
|
35
|
+
WantedBy=multi-user.target
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Nginx 服务器部署指南(纯服务器,非 Docker)
|
|
2
|
+
|
|
3
|
+
> 本目录提供 **ssh 类型部署**场景下前端站点的 Nginx 服务器端配置模板。
|
|
4
|
+
> Docker 场景(Nginx 容器托管前端)请使用 `templates/deploy-docker/nginx.conf`。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 两种 Nginx 场景怎么选
|
|
9
|
+
|
|
10
|
+
| 场景 | 部署类型 | 配置文件 | Nginx 位置 |
|
|
11
|
+
|:---|:---|:---|:---|
|
|
12
|
+
| **纯服务器**:构建产物上传到服务器 Nginx 静态目录,后端跑进程/systemd | `ssh`(推荐)/ `sftp` | 本目录 `nginx-site.conf` | 服务器 `/etc/nginx/conf.d/` |
|
|
13
|
+
| **容器化**:前端打成镜像由 Nginx 容器托管 | `docker` | `deploy-docker/nginx.conf` | 镜像内 `/etc/nginx/conf.d/` |
|
|
14
|
+
|
|
15
|
+
## 快速开始(前端 ssh 部署 + 服务器 Nginx 托管)
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# 1. 服务器端(只需一次):复制站点配置并替换占位符
|
|
19
|
+
sudo cp nginx-site.conf /etc/nginx/conf.d/admin-web.conf
|
|
20
|
+
sudo sed -i 's/{{DOMAIN}}/admin.example.com/; s|{{APP_DIR}}|/var/www/html/admin-web|; s|{{BACKEND_HOST}}|127.0.0.1:8080|' /etc/nginx/conf.d/admin-web.conf
|
|
21
|
+
sudo nginx -t && sudo nginx -s reload
|
|
22
|
+
|
|
23
|
+
# 2. PROJECT.yaml 配置 ssh 类型部署
|
|
24
|
+
# remote_dir: /var/www/html/admin-web
|
|
25
|
+
# script: sudo nginx -s reload
|
|
26
|
+
|
|
27
|
+
# 3. 部署(构建 → 上传 → 重载 Nginx)
|
|
28
|
+
speccore deploy --env staging --platform admin-web
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## 模板包含内容
|
|
32
|
+
|
|
33
|
+
- SPA 路由回退(`try_files` → `/index.html`)
|
|
34
|
+
- gzip 压缩
|
|
35
|
+
- 静态资源长期缓存(`immutable`)
|
|
36
|
+
- `/api/` 反向代理到后端(同机 `127.0.0.1:8080` 或跨机内网地址)
|
|
37
|
+
- WebSocket 升级(注释备用)
|
|
38
|
+
- 健康检查端点透传(`/healthz` → 后端 `/actuator/health`,注释备用)
|
|
39
|
+
- HTTPS server 块(证书就绪后启用)
|
|
40
|
+
- 隐藏文件访问拦截
|
|
41
|
+
|
|
42
|
+
## 占位符
|
|
43
|
+
|
|
44
|
+
| 占位符 | 说明 | 示例 |
|
|
45
|
+
|:---|:---|:---|
|
|
46
|
+
| `{{DOMAIN}}` | 站点域名或 IP | `admin.example.com` |
|
|
47
|
+
| `{{APP_DIR}}` | 静态资源目录(= `remote_dir`) | `/var/www/html/admin-web` |
|
|
48
|
+
| `{{BACKEND_HOST}}` | 后端地址 | `127.0.0.1:8080` |
|
|
49
|
+
|
|
50
|
+
## 与冒烟测试联动
|
|
51
|
+
|
|
52
|
+
部署完成后可在 `.speccore/environments/{env}.yaml` 的 `tests.base_urls` 配置站点地址,
|
|
53
|
+
`speccore verify` 的部署后冒烟将自动访问验证:
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
tests:
|
|
57
|
+
base_urls:
|
|
58
|
+
admin-web: https://admin.example.com
|
|
59
|
+
```
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# ═══════════════════════════════════════════════════════════
|
|
2
|
+
# Nginx 服务器站点配置模板(纯服务器部署,非 Docker 场景)
|
|
3
|
+
# ═══════════════════════════════════════════════════════════
|
|
4
|
+
#
|
|
5
|
+
# 适用场景:speccore deploy 的 ssh 类型部署,前端构建产物
|
|
6
|
+
# 上传到 Nginx 服务器静态目录,后端以进程/服务方式跑在
|
|
7
|
+
# 同一台(或另一台)服务器上。
|
|
8
|
+
#
|
|
9
|
+
# 用法:
|
|
10
|
+
# 1. 复制本文件到服务器: /etc/nginx/conf.d/<your-site>.conf
|
|
11
|
+
# (或 /etc/nginx/sites-available/ + sites-enabled 软链)
|
|
12
|
+
# 2. 替换 {{占位符}}
|
|
13
|
+
# 3. 校验并重载: sudo nginx -t && sudo nginx -s reload
|
|
14
|
+
#
|
|
15
|
+
# 与 PROJECT.yaml 的对应关系(ssh 类型部署):
|
|
16
|
+
# remote_dir → 下方 root 指向的目录
|
|
17
|
+
# script → sudo nginx -s reload(部署完成后重载配置)
|
|
18
|
+
#
|
|
19
|
+
# 占位符说明:
|
|
20
|
+
# {{DOMAIN}} 站点域名(或服务器 IP)
|
|
21
|
+
# {{APP_DIR}} 静态资源目录(= remote_dir,如 /var/www/html/admin-web)
|
|
22
|
+
# {{BACKEND_HOST}} 后端地址(同机为 127.0.0.1:8080,跨机为内网 IP:端口)
|
|
23
|
+
# ═══════════════════════════════════════════════════════════
|
|
24
|
+
|
|
25
|
+
# ── HTTP(开发/测试环境,或 HTTPS 前的重定向入口)──
|
|
26
|
+
server {
|
|
27
|
+
listen 80;
|
|
28
|
+
server_name {{DOMAIN}};
|
|
29
|
+
|
|
30
|
+
# 有证书后启用 HTTPS,取消注释并将整块 HTTP 改为重定向:
|
|
31
|
+
# return 301 https://$host$request_uri;
|
|
32
|
+
|
|
33
|
+
include /etc/nginx/conf.d/_site-common.conf;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# ── HTTPS(生产环境,证书就绪后启用)──
|
|
37
|
+
# server {
|
|
38
|
+
# listen 443 ssl http2;
|
|
39
|
+
# server_name {{DOMAIN}};
|
|
40
|
+
#
|
|
41
|
+
# ssl_certificate /etc/nginx/ssl/{{DOMAIN}}.pem;
|
|
42
|
+
# ssl_certificate_key /etc/nginx/ssl/{{DOMAIN}}.key;
|
|
43
|
+
# ssl_protocols TLSv1.2 TLSv1.3;
|
|
44
|
+
# ssl_session_cache shared:SSL:10m;
|
|
45
|
+
#
|
|
46
|
+
# include /etc/nginx/conf.d/_site-common.conf;
|
|
47
|
+
# }
|
|
48
|
+
|
|
49
|
+
# ── 站点公共配置(HTTP/HTTPS 共用,独立成文件避免重复)──
|
|
50
|
+
# 保存为 /etc/nginx/conf.d/_site-common.conf 后 include,
|
|
51
|
+
# 或直接展开合并进上方 server 块。
|
|
52
|
+
|
|
53
|
+
# 静态资源根目录(= PROJECT.yaml 中 ssh 类型的 remote_dir)
|
|
54
|
+
root {{APP_DIR}};
|
|
55
|
+
index index.html;
|
|
56
|
+
|
|
57
|
+
# gzip 压缩(减少传输体积)
|
|
58
|
+
gzip on;
|
|
59
|
+
gzip_min_length 1k;
|
|
60
|
+
gzip_comp_level 5;
|
|
61
|
+
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
|
|
62
|
+
|
|
63
|
+
# ── 前端路由(SPA 应用)──
|
|
64
|
+
location / {
|
|
65
|
+
try_files $uri $uri/ /index.html;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# ── 静态资源长期缓存 ──
|
|
69
|
+
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
|
|
70
|
+
expires 1y;
|
|
71
|
+
add_header Cache-Control "public, immutable";
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
# ── API 反向代理到后端(同机后端)──
|
|
75
|
+
location /api/ {
|
|
76
|
+
proxy_pass http://{{BACKEND_HOST}}/api/;
|
|
77
|
+
proxy_set_header Host $host;
|
|
78
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
79
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
80
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
81
|
+
proxy_connect_timeout 10s;
|
|
82
|
+
proxy_read_timeout 60s;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# ── WebSocket 升级(后端含长连接/推送时启用)──
|
|
86
|
+
# location /ws {
|
|
87
|
+
# proxy_pass http://{{BACKEND_HOST}};
|
|
88
|
+
# proxy_http_version 1.1;
|
|
89
|
+
# proxy_set_header Upgrade $http_upgrade;
|
|
90
|
+
# proxy_set_header Connection "upgrade";
|
|
91
|
+
# proxy_read_timeout 3600s;
|
|
92
|
+
# }
|
|
93
|
+
|
|
94
|
+
# ── 后端健康检查端点透传(部署后验证用)──
|
|
95
|
+
# location = /healthz {
|
|
96
|
+
# proxy_pass http://{{BACKEND_HOST}}/actuator/health;
|
|
97
|
+
# access_log off;
|
|
98
|
+
# }
|
|
99
|
+
|
|
100
|
+
# ── 禁止访问隐藏文件 ──
|
|
101
|
+
location ~ /\. {
|
|
102
|
+
deny all;
|
|
103
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# 通用部署脚本模板
|
|
2
|
+
|
|
3
|
+
> 本目录提供 `script` 类型部署的**开箱即用脚本实体**,覆盖 Jenkins 触发、FTP 上传、密码 SSH、Compose 编排、Python 服务五类场景。
|
|
4
|
+
> 对应 `templates/deploy-examples.yaml` 中 script 类型各节的注释示例。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 脚本清单
|
|
9
|
+
|
|
10
|
+
| 脚本 | 场景 | 依赖 | 关键环境变量 |
|
|
11
|
+
|:---|:---|:---|:---|
|
|
12
|
+
| `trigger-jenkins.sh <job>` | 触发 Jenkins 构建发布 | `curl` | `JENKINS_URL` `JENKINS_USER` `JENKINS_TOKEN` |
|
|
13
|
+
| `deploy-ftp.sh [dir]` | 虚拟主机 FTP 上传(无 SSH 权限) | `lftp` | `FTP_USER` `FTP_PASS` `FTP_HOST` `FTP_REMOTE_DIR` |
|
|
14
|
+
| `deploy-password-ssh.sh [dir]` | 密码认证 SSH 部署(无密钥) | `sshpass` | `SSH_USER` `SSH_PASSWORD` `SSH_HOST` `SSH_REMOTE_DIR` |
|
|
15
|
+
| `deploy-compose.sh [file]` | 服务器端 Compose 编排部署 | `docker-compose` | — |
|
|
16
|
+
| `deploy-python.sh [dir]` | Python gunicorn + systemd 部署 | `rsync` | `DEPLOY_HOST` `DEPLOY_DIR` `SERVICE_NAME` |
|
|
17
|
+
|
|
18
|
+
## 目录组织约定
|
|
19
|
+
|
|
20
|
+
部署脚本按「执行位置」分三处存放,各司其职:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
① 包内模板 templates/deploy-*/
|
|
24
|
+
├── deploy-scripts/ ← 通用脚本实体(本目录,script 类型直接引用)
|
|
25
|
+
├── deploy-docker/ ← Docker 构建素材 + 服务器端容器管理脚本(deploy-remote.sh)
|
|
26
|
+
├── deploy-java/ ← Java systemd/Docker 素材 + 服务器端脚本(deploy.sh)
|
|
27
|
+
└── deploy-nginx/ ← 纯服务器 Nginx 站点配置
|
|
28
|
+
↓(npm 安装后用户手动 cp 到工程)
|
|
29
|
+
|
|
30
|
+
② 用户项目 .speccore/environments/scripts/(init 自动生成)
|
|
31
|
+
├── deploy.sh ← 通用 script 类型骨架(TODO 待填)
|
|
32
|
+
├── ecosystem.config.js ← pm2 类型
|
|
33
|
+
├── k8s-deployment.yaml ← k8s 类型
|
|
34
|
+
├── java-systemd.service / java-restart.sh ← ssh 类型 Java
|
|
35
|
+
└── values-{env}.yaml ← helm 类型(按环境生成)
|
|
36
|
+
↓(speccore deploy 按 script/pm2_config/output_dir 字段引用)
|
|
37
|
+
|
|
38
|
+
③ 端工程内 scripts/(用户自维护)
|
|
39
|
+
← 端专属脚本,config.script 用 ./scripts/xxx.sh 相对路径引用
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
> **路径解析(v8.3.296+)**:引擎对 `script` / `pm2_config` / k8s manifest / helm values 做双基准解析——先在端目录(code_path)找,回退项目根。`./scripts/xxx.sh` 与 `.speccore/environments/scripts/xxx` 两种写法都通。
|
|
43
|
+
|
|
44
|
+
## 使用方式
|
|
45
|
+
|
|
46
|
+
```yaml
|
|
47
|
+
# PROJECT.yaml(script 类型)
|
|
48
|
+
deploy:
|
|
49
|
+
staging:
|
|
50
|
+
type: script
|
|
51
|
+
build_cmd: npm run build
|
|
52
|
+
script: ./scripts/deploy-password-ssh.sh # 端工程内脚本(推荐)
|
|
53
|
+
# 或引用项目根资产:
|
|
54
|
+
# script: .speccore/environments/scripts/deploy.sh
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
敏感信息(密码/token)一律通过环境变量注入,勿写入配置文件或 git:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
SSH_USER=deployer SSH_PASSWORD=xxx SSH_HOST=server ./scripts/deploy-password-ssh.sh dist
|
|
61
|
+
```
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ═══════════════════════════════════════════════════════════
|
|
3
|
+
# Docker Compose 部署脚本(服务器端执行)
|
|
4
|
+
# ═══════════════════════════════════════════════════════════
|
|
5
|
+
# 用途:script 类型部署,服务器端统一拉取并启动前后端编排
|
|
6
|
+
# 用法:./deploy-compose.sh [compose-file]
|
|
7
|
+
# 示例:./deploy-compose.sh /opt/deploy/docker-compose.yml
|
|
8
|
+
# ═══════════════════════════════════════════════════════════
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
COMPOSE_FILE="${1:-/opt/deploy/docker-compose.yml}"
|
|
12
|
+
|
|
13
|
+
echo "🚀 Compose 部署: $COMPOSE_FILE"
|
|
14
|
+
docker-compose -f "$COMPOSE_FILE" pull
|
|
15
|
+
docker-compose -f "$COMPOSE_FILE" up -d
|
|
16
|
+
|
|
17
|
+
echo "📋 运行状态:"
|
|
18
|
+
docker-compose -f "$COMPOSE_FILE" ps
|
|
19
|
+
echo "✅ 部署完成"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ═══════════════════════════════════════════════════════════
|
|
3
|
+
# FTP 上传部署脚本(lftp)
|
|
4
|
+
# ═══════════════════════════════════════════════════════════
|
|
5
|
+
# 用途:script 类型部署,无 SSH 权限只有 FTP 的虚拟主机场景
|
|
6
|
+
# 环境变量(由用户 shell 环境注入,勿写入 git):
|
|
7
|
+
# FTP_USER / FTP_PASS / FTP_HOST / FTP_REMOTE_DIR
|
|
8
|
+
# 用法:FTP_USER=u FTP_PASS=p FTP_HOST=h ./deploy-ftp.sh [本地目录]
|
|
9
|
+
# ═══════════════════════════════════════════════════════════
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
LOCAL_DIR="${1:-dist}"
|
|
13
|
+
FTP_REMOTE_DIR="${FTP_REMOTE_DIR:-/public_html}"
|
|
14
|
+
|
|
15
|
+
if [ -z "${FTP_USER:-}" ] || [ -z "${FTP_PASS:-}" ] || [ -z "${FTP_HOST:-}" ]; then
|
|
16
|
+
echo "❌ 缺少环境变量: FTP_USER / FTP_PASS / FTP_HOST"
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
echo "🚀 FTP 上传: $LOCAL_DIR → $FTP_HOST:$FTP_REMOTE_DIR"
|
|
21
|
+
|
|
22
|
+
lftp -u "$FTP_USER,$FTP_PASS" "$FTP_HOST" <<INNER_EOF
|
|
23
|
+
set ssl:verify-certificate no
|
|
24
|
+
mirror -R "$LOCAL_DIR" "$FTP_REMOTE_DIR"
|
|
25
|
+
bye
|
|
26
|
+
INNER_EOF
|
|
27
|
+
|
|
28
|
+
echo "✅ 上传完成"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ═══════════════════════════════════════════════════════════
|
|
3
|
+
# 密码认证 SSH 部署脚本(sshpass)
|
|
4
|
+
# ═══════════════════════════════════════════════════════════
|
|
5
|
+
# 用途:script 类型部署,无密钥只有密码的 SSH 场景
|
|
6
|
+
# 前置:安装 sshpass(macOS: brew install sshpass;Ubuntu: apt-get install sshpass)
|
|
7
|
+
# 环境变量(由用户 shell 环境注入,勿写入 git):
|
|
8
|
+
# SSH_USER / SSH_PASSWORD / SSH_HOST / SSH_REMOTE_DIR
|
|
9
|
+
# 用法:SSH_USER=u SSH_PASSWORD=p ./deploy-password-ssh.sh [本地目录]
|
|
10
|
+
# ═══════════════════════════════════════════════════════════
|
|
11
|
+
set -euo pipefail
|
|
12
|
+
|
|
13
|
+
LOCAL_DIR="${1:-dist}"
|
|
14
|
+
SSH_REMOTE_DIR="${SSH_REMOTE_DIR:-/var/www/html}"
|
|
15
|
+
|
|
16
|
+
if [ -z "${SSH_USER:-}" ] || [ -z "${SSH_PASSWORD:-}" ] || [ -z "${SSH_HOST:-}" ]; then
|
|
17
|
+
echo "❌ 缺少环境变量: SSH_USER / SSH_PASSWORD / SSH_HOST"
|
|
18
|
+
exit 1
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
echo "🚀 SSH 上传: $LOCAL_DIR → $SSH_USER@$SSH_HOST:$SSH_REMOTE_DIR"
|
|
22
|
+
|
|
23
|
+
sshpass -p "$SSH_PASSWORD" scp -r "$LOCAL_DIR"/* "$SSH_USER@$SSH_HOST:$SSH_REMOTE_DIR/"
|
|
24
|
+
sshpass -p "$SSH_PASSWORD" ssh "$SSH_USER@$SSH_HOST" "sudo nginx -s reload"
|
|
25
|
+
|
|
26
|
+
echo "✅ 部署完成"
|