Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
pac
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tools
pac
Commits
1ab5132d
Commit
1ab5132d
authored
Sep 03, 2026
by
luoqi
Browse files
Options
Browse Files
Download
Plain Diff
merge: feat/deploy-docs-script → test(文档站单独部署 + 硬校验 Server URL)
parents
9965af0d
46f7f00e
Pipeline
#3664
failed in 0 seconds
Changes
2
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
105 additions
and
0 deletions
+105
-0
deploy/README.md
+20
-0
deploy/deploy-docs.sh
+85
-0
No files found.
deploy/README.md
View file @
1ab5132d
...
@@ -10,6 +10,7 @@
...
@@ -10,6 +10,7 @@
|---|---|---|
|---|---|---|
|
`deploy/gen-env.sh`
| 生成
`.env`
(密钥随机 + 生产开关 + 业务值注入 + 缺失报告) | 拒覆盖已有(
`FORCE=1`
强制) |
|
`deploy/gen-env.sh`
| 生成
`.env`
(密钥随机 + 生产开关 + 业务值注入 + 缺失报告) | 拒覆盖已有(
`FORCE=1`
强制) |
|
`deploy/deploy-prod.sh`
| 拉码 + build + 重建容器 + 硬验证(镜像/迁移/health) | ✅ 反复跑 |
|
`deploy/deploy-prod.sh`
| 拉码 + build + 重建容器 + 硬验证(镜像/迁移/health) | ✅ 反复跑 |
|
`deploy/deploy-docs.sh`
|
**文档站单独部署**
(pac-docs 不在 deploy-prod.sh 里)+ 硬验证 OpenAPI Server URL | ✅ 反复跑 |
|
`deploy/first-import.sh`
| 数据首灌:seed + 存量 + 重算画像/计划 | ✅ 可重跑 |
|
`deploy/first-import.sh`
| 数据首灌:seed + 存量 + 重算画像/计划 | ✅ 可重跑 |
---
---
...
@@ -34,6 +35,25 @@ build 阶段不影响服务(老容器一直跑),停机只发生在重建那一
...
@@ -34,6 +35,25 @@ build 阶段不影响服务(老容器一直跑),停机只发生在重建那一
> 改了 `NEXT_PUBLIC_*`(前端 build-time 变量)必须走本脚本重 build;只改后端 `.env` 用 `docker compose -f docker-compose.prod.yml restart pac-service` 即可。
> 改了 `NEXT_PUBLIC_*`(前端 build-time 变量)必须走本脚本重 build;只改后端 `.env` 用 `docker compose -f docker-compose.prod.yml restart pac-service` 即可。
### 改了文档(`apps/pac-docs/`)要另外跑一条
`deploy-prod.sh`
**只构建 pac-migrate / pac-service / pac-web,不含 pac-docs**
—— 文档站要单独部署:
```
bash
bash deploy/deploy-docs.sh
```
**为什么分开**
:pac-docs 的 Dockerfile 是
`COPY . .`
(整个仓库),任何代码改动都会让它的
build 缓存失效、Next.js SSG 全量重跑。实测(2026-09-03 测试服):什么都没改
**3 秒**
,
改了后端一行代码
**111 秒**
。而绝大多数部署都是改后端、文档没动 —— 并进主流程等于每次白花约 2 分钟。
⚠️
**不要手敲 `docker compose build pac-docs`**
。docs 镜像里 OpenAPI 的「Server URL」来自
build arg
`DOCS_API_URL`
,它回落到
`NEXT_PUBLIC_API_BASE_URL`
,而后者在
**`apps/pac-web/.env`**
里(不在
`pac-service/.env`
)。少传一个
`--env-file`
就会变成
`http://localhost:3101`
,
**且构建照样成功、不报任何错**
—— 只有点开 API 参考页才看得出来,对接方照着填会打不通
(2026-09-03 实际踩到,线上挂了几天没人发现)。
`deploy-docs.sh`
固化了两个 env-file
并在构建后硬校验 servers 地址,写错立刻失败。
---
---
## 2. 新环境从零上线(换服务器 / 首次生产)
## 2. 新环境从零上线(换服务器 / 首次生产)
...
...
deploy/deploy-docs.sh
0 → 100755
View file @
1ab5132d
#!/usr/bin/env bash
# PAC 文档站(pac-docs)单独部署
#
# 【为什么不并进 deploy-prod.sh】
# pac-docs 的 Dockerfile 里是 `COPY . .`(整个仓库),所以**任何**代码改动都会让它的
# build 缓存失效、Next.js SSG 全量重跑。实测(2026-09-03,测试服):
# 什么都没改 → 3 秒 (17/17 层缓存命中)
# 改了后端代码一行 → 111 秒(COPY 之后全失效)
# 而绝大多数部署都是改后端、文档没动 —— 并进主流程等于每次白白多花约 2 分钟。
# 故保持分离:改了 apps/pac-docs/ 下的东西才跑本脚本。
#
# 【为什么要有这个脚本,而不是手敲 docker compose】
# docs 镜像里的 OpenAPI「Server URL」来自 build arg DOCS_API_URL,而 compose 里它是
# ${DOCS_API_URL:-${NEXT_PUBLIC_API_BASE_URL:-http://localhost:3101}}
# NEXT_PUBLIC_API_BASE_URL 在 **apps/pac-web/.env** 里(不在 pac-service/.env)。
# 手敲时少传一个 --env-file 就会一路回落到 localhost:3101 —— 而且**构建照样成功、
# 不报任何错**,只有点开 API 参考页才看得出来,对接方照着填就打不通。
# 2026-09-03 实际踩到:之前几次手工重建 docs 都只传了 pac-service/.env,
# 线上 API 参考页的 Server URL 一直是 localhost:3101。
# → 本脚本固化两个 env-file,并在构建后**硬校验** servers 地址,写错立刻失败而非静默上线。
#
# 用法(服务器上,~/pac):
# bash deploy/deploy-docs.sh # 部署文档站
# COMPOSE_MANAGED=1 bash deploy/deploy-docs.sh # 托管 DB 形态的机器(同 deploy-prod.sh)
# bash deploy/deploy-docs.sh --no-pull # 跳过 git 拉取(代码已就位时)
set
-euo
pipefail
log
()
{
printf
'\n\033[1;36m== %s ==\033[0m\n'
"
$*
"
;
}
die
()
{
printf
'\033[1;31mFAIL: %s\033[0m\n'
"
$*
"
>
&2
;
exit
1
;
}
main
()
{
cd
"
$(
dirname
"
$0
"
)
/.."
if
[[
"
${
1
:-}
"
!=
"--no-pull"
]]
;
then
log
"git 拉取(
$(
git rev-parse
--abbrev-ref
HEAD
)
)"
git pull
--ff-only
fi
# compose 组装与 deploy-prod.sh 保持一致 —— 两个 env-file 缺一不可(见文件头说明)
local
COMPOSE
=(
docker compose
-f
docker-compose.prod.yml
)
[[
"
${
COMPOSE_MANAGED
:-
0
}
"
==
"1"
]]
&&
COMPOSE+
=(
-f
docker-compose.managed.yml
)
COMPOSE+
=(
--env-file
apps/pac-service/.env
--env-file
apps/pac-web/.env
)
# 构建前先把将要注入的地址打出来,肉眼可核
local
api_url
api_url
=
$(
"
${
COMPOSE
[@]
}
"
config 2>/dev/null |
grep
-m1
'DOCS_API_URL:'
| sed
's/.*DOCS_API_URL: *//'
)
log
"OpenAPI Server URL 将注入为:
${
api_url
:-
(空)
}
"
[[
-n
"
$api_url
"
]]
||
die
"解析不到 DOCS_API_URL —— 检查 apps/pac-web/.env 是否有 NEXT_PUBLIC_API_BASE_URL"
case
"
$api_url
"
in
*
localhost
*
|
*
127.0.0.1
*
)
die
"DOCS_API_URL 解析成了本地地址(
$api_url
)。
多半是 apps/pac-web/.env 缺 NEXT_PUBLIC_API_BASE_URL,或该文件不存在。
这么构建出来的 API 参考页,对接方照着填会打不通。"
;;
esac
log
"build pac-docs(显式,不和 up 混 —— 同 deploy-prod.sh 的理由)"
"
${
COMPOSE
[@]
}
"
build pac-docs
log
"force-recreate(不信 compose 的重建判定)"
"
${
COMPOSE
[@]
}
"
up
-d
--force-recreate
pac-docs
# ── 验证 1/2:镜像里的 spec 确实带对了地址(而不是只看构建日志) ──
log
"验证 1/2:容器内 openapi spec 的 servers"
local
got
got
=
$(
docker
exec
"
$(
"
${
COMPOSE
[@]
}
"
ps
-q
pac-docs
)
"
\
node
-e
'const d=require("/app/apps/pac-docs/openapi/pac.json");process.stdout.write(String((d.servers&&d.servers[0]&&d.servers[0].url)||""))'
2>/dev/null
||
true
)
[[
"
$got
"
==
"
$api_url
"
]]
\
||
die
"spec 里的 servers 是「
$got
」,期望「
$api_url
」"
printf
' servers OK (%s)\n'
"
$got
"
# ── 验证 2/2:站点起得来 ──
log
"验证 2/2:文档站可访问"
local
code
for
_
in
$(
seq 1 20
)
;
do
code
=
$(
curl
-s
-o
/dev/null
-w
'%{http_code}'
http://localhost:3102/
||
true
)
[[
"
$code
"
==
"200"
]]
&&
break
sleep 2
done
[[
"
$code
"
==
"200"
]]
||
die
"文档站未就绪(最后一次 HTTP
$code
)"
printf
' docs 200(loopback)\n'
log
"文档站部署成功 ✅
$(
git log
--oneline
-1
)
"
}
main
"
$@
"
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment