listpage_cli 0.0.297 → 0.0.298
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/bin/adapters/cli-interaction.js +38 -10
- package/bin/app/parse-args.js +2 -0
- package/bin/commands/deploy-project-command.js +1 -0
- package/bin/services/deploy-project-service.js +28 -22
- package/package.json +1 -1
- package/templates/backend-template/package.json.tmpl +1 -1
- package/templates/frontend-template/package.json.tmpl +2 -2
|
@@ -134,18 +134,46 @@ async function askOverwrite() {
|
|
|
134
134
|
}
|
|
135
135
|
return (0, interaction_result_1.interactionValue)(result.value.ok);
|
|
136
136
|
}
|
|
137
|
+
const HELP_ANSI = {
|
|
138
|
+
reset: "\u001b[0m",
|
|
139
|
+
dim: "\u001b[2m",
|
|
140
|
+
cyan: "\u001b[36m",
|
|
141
|
+
green: "\u001b[32m",
|
|
142
|
+
yellow: "\u001b[33m",
|
|
143
|
+
};
|
|
144
|
+
const HELP_USE_COLOR = process.env.NO_COLOR === undefined;
|
|
145
|
+
function helpColor(text, color) {
|
|
146
|
+
if (!HELP_USE_COLOR) {
|
|
147
|
+
return text;
|
|
148
|
+
}
|
|
149
|
+
return `${HELP_ANSI[color]}${text}${HELP_ANSI.reset}`;
|
|
150
|
+
}
|
|
137
151
|
function printHelp() {
|
|
138
152
|
const h = [
|
|
139
|
-
"
|
|
140
|
-
"
|
|
141
|
-
"
|
|
142
|
-
"
|
|
143
|
-
"
|
|
144
|
-
"
|
|
145
|
-
"
|
|
146
|
-
"
|
|
147
|
-
"
|
|
148
|
-
"
|
|
153
|
+
helpColor("listpage_cli 命令说明", "cyan"),
|
|
154
|
+
"",
|
|
155
|
+
` ${helpColor("init", "green")}`,
|
|
156
|
+
` 用法: ${helpColor("listpage_cli init", "dim")}`,
|
|
157
|
+
" 说明: 进入中文引导式交互,按提示填写即可",
|
|
158
|
+
"",
|
|
159
|
+
` ${helpColor("install-skill", "green")}`,
|
|
160
|
+
` 用法: ${helpColor("listpage_cli install-skill [skillName] [--project]", "dim")}`,
|
|
161
|
+
" 说明: 安装技能到 Cursor;默认 skillName 为 test,安装到当前命令执行目录的 .cursor/skills/",
|
|
162
|
+
"",
|
|
163
|
+
` ${helpColor("build-project", "green")}`,
|
|
164
|
+
` 用法: ${helpColor("listpage_cli build-project", "dim")}`,
|
|
165
|
+
" 说明: 非交互校验当前目录是否为有效项目根(需存在 listpage.config.json)",
|
|
166
|
+
"",
|
|
167
|
+
` ${helpColor("release-project", "green")}`,
|
|
168
|
+
` 用法: ${helpColor("listpage_cli release-project [tag] [--profile dev] [--platform linux/amd64] [--env KEY=VALUE]", "dim")}`,
|
|
169
|
+
" 说明: 先校验 .listpage/output 产物,再按 login/build/tag/push 执行 Docker 发布",
|
|
170
|
+
` 备注: ${helpColor("参数优先级为 CLI > profile > base", "yellow")}`,
|
|
171
|
+
"",
|
|
172
|
+
` ${helpColor("deploy-project", "green")}`,
|
|
173
|
+
` 用法: ${helpColor("listpage_cli deploy-project [tag] [--profile dev] [--platform linux/amd64] [--env KEY=VALUE] [--skip-image]", "dim")}`,
|
|
174
|
+
" 说明: 使用 docker.remote + docker.container 执行部署,支持 ports[] 与 envFile/env 合并",
|
|
175
|
+
` 备注: ${helpColor("默认会清理并拉取镜像;传入 --skip-image 时只执行容器相关步骤(假定镜像已是最新且已存在)", "yellow")}`,
|
|
176
|
+
` ${helpColor("参数优先级为 CLI > profile > base", "yellow")}`,
|
|
149
177
|
].join("\n");
|
|
150
178
|
console.log(h);
|
|
151
179
|
}
|
package/bin/app/parse-args.js
CHANGED
|
@@ -46,10 +46,12 @@ function parseCommandOptions(rawArgs) {
|
|
|
46
46
|
const platform = readSingleOption(args, "platform");
|
|
47
47
|
const envEntries = readMultiOption(args, "env");
|
|
48
48
|
const env = parseEnvEntries(envEntries);
|
|
49
|
+
const skipImage = args.includes("--skip-image");
|
|
49
50
|
return {
|
|
50
51
|
profile,
|
|
51
52
|
platform,
|
|
52
53
|
env: Object.keys(env).length > 0 ? env : undefined,
|
|
54
|
+
skipImage: skipImage || undefined,
|
|
53
55
|
};
|
|
54
56
|
}
|
|
55
57
|
function parseCommandPositionals(rawArgs) {
|
|
@@ -90,6 +90,7 @@ async function runDeployProjectFlow(deps) {
|
|
|
90
90
|
executionInput,
|
|
91
91
|
resolve: deps.fs.resolve,
|
|
92
92
|
readText: deps.fs.readText,
|
|
93
|
+
skipImage: deps.skipImage === true,
|
|
93
94
|
});
|
|
94
95
|
}
|
|
95
96
|
function resolveRuntimeConfig(config, cliOverrides) {
|
|
@@ -142,28 +143,6 @@ async function runDockerDeploy(input) {
|
|
|
142
143
|
const { client, executionInput } = input;
|
|
143
144
|
const remoteImage = executionInput.remoteImage;
|
|
144
145
|
logDeployStep("run", `开始部署镜像: ${remoteImage}`);
|
|
145
|
-
try {
|
|
146
|
-
logDeployStep("run", `检查本地镜像是否存在: ${remoteImage}`);
|
|
147
|
-
const exists = await client.imageExists(remoteImage);
|
|
148
|
-
logDeployStep("run", `本地镜像检查结果: exists=${exists ? "yes" : "no"}`);
|
|
149
|
-
if (exists) {
|
|
150
|
-
logDeployStep("run", `删除旧镜像: ${remoteImage}`);
|
|
151
|
-
await client.removeImage(remoteImage);
|
|
152
|
-
logDeployStep("run", `旧镜像删除完成: ${remoteImage}`);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
catch (error) {
|
|
156
|
-
return (0, command_result_1.commandError)(`[${DEPLOY_STAGE}][run] 清理镜像缓存失败: ${toErrorMessage(error)}`, command_result_1.COMMAND_ERROR_CODES.executionFailed, 1);
|
|
157
|
-
}
|
|
158
|
-
try {
|
|
159
|
-
const auth = buildPullAuth(executionInput.docker);
|
|
160
|
-
logDeployStep("run", `开始拉取镜像: ${remoteImage} (auth=${auth ? "yes" : "no"})`);
|
|
161
|
-
await client.pullImage(remoteImage, auth);
|
|
162
|
-
logDeployStep("run", `镜像拉取完成: ${remoteImage}`);
|
|
163
|
-
}
|
|
164
|
-
catch (error) {
|
|
165
|
-
return (0, command_result_1.commandError)(`[${DEPLOY_STAGE}][run] 拉取镜像失败: ${toErrorMessage(error)}`, command_result_1.COMMAND_ERROR_CODES.executionFailed, 1);
|
|
166
|
-
}
|
|
167
146
|
try {
|
|
168
147
|
logDeployStep("run", `检查已有容器: ${executionInput.runtime.containerName}`);
|
|
169
148
|
const existingContainerId = await client.findContainerIdByName(executionInput.runtime.containerName);
|
|
@@ -179,6 +158,33 @@ async function runDockerDeploy(input) {
|
|
|
179
158
|
catch (error) {
|
|
180
159
|
return (0, command_result_1.commandError)(`[${DEPLOY_STAGE}][run] 替换容器失败: ${toErrorMessage(error)}`, command_result_1.COMMAND_ERROR_CODES.executionFailed, 1);
|
|
181
160
|
}
|
|
161
|
+
if (input.skipImage !== true) {
|
|
162
|
+
try {
|
|
163
|
+
logDeployStep("run", `检查本地镜像是否存在: ${remoteImage}`);
|
|
164
|
+
const exists = await client.imageExists(remoteImage);
|
|
165
|
+
logDeployStep("run", `本地镜像检查结果: exists=${exists ? "yes" : "no"}`);
|
|
166
|
+
if (exists) {
|
|
167
|
+
logDeployStep("run", `删除旧镜像: ${remoteImage}`);
|
|
168
|
+
await client.removeImage(remoteImage);
|
|
169
|
+
logDeployStep("run", `旧镜像删除完成: ${remoteImage}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
return (0, command_result_1.commandError)(`[${DEPLOY_STAGE}][run] 清理镜像缓存失败: ${toErrorMessage(error)}`, command_result_1.COMMAND_ERROR_CODES.executionFailed, 1);
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
const auth = buildPullAuth(executionInput.docker);
|
|
177
|
+
logDeployStep("run", `开始拉取镜像: ${remoteImage} (auth=${auth ? "yes" : "no"})`);
|
|
178
|
+
await client.pullImage(remoteImage, auth);
|
|
179
|
+
logDeployStep("run", `镜像拉取完成: ${remoteImage}`);
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
return (0, command_result_1.commandError)(`[${DEPLOY_STAGE}][run] 拉取镜像失败: ${toErrorMessage(error)}`, command_result_1.COMMAND_ERROR_CODES.executionFailed, 1);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
logDeployStep("run", `跳过镜像处理: 按照 --skip-image 假定镜像已存在且为最新`);
|
|
187
|
+
}
|
|
182
188
|
let createContainerInput;
|
|
183
189
|
try {
|
|
184
190
|
createContainerInput = (0, dockerode_client_1.toRuntimeContainerInput)({
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"react": "^19.2.0",
|
|
14
14
|
"react-dom": "^19.2.0",
|
|
15
|
-
"listpage-next": "~0.0.
|
|
15
|
+
"listpage-next": "~0.0.298",
|
|
16
16
|
"react-router-dom": ">=6.0.0",
|
|
17
17
|
"@ant-design/v5-patch-for-react-19": "~1.0.3",
|
|
18
18
|
"ahooks": "^3.9.5",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"styled-components": "^6.1.19",
|
|
24
24
|
"mobx": "~6.15.0",
|
|
25
25
|
"@ant-design/icons": "~6.0.2",
|
|
26
|
-
"listpage-components": "~0.0.
|
|
26
|
+
"listpage-components": "~0.0.298",
|
|
27
27
|
"lucide-react": "~0.575.0"
|
|
28
28
|
"mobx-react-lite": "~4.1.1"
|
|
29
29
|
},
|