From 49643719b036807638724fbaf0fbe52c559f5b2d Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Tue, 3 Nov 2026 11:17:36 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E9=83=A8=E7=BD=B2):=20=E5=BC=80=E5=8F=91?= =?UTF-8?q?=E6=9C=BA=E4=B8=8A=E7=BC=96=E7=9A=84=E5=90=8E=E7=AB=AF=E5=88=B0?= =?UTF-8?q?=E7=BA=BF=E4=B8=8A=E8=B5=B7=E4=B8=8D=E6=9D=A5=EF=BC=88=E7=BC=BA?= =?UTF-8?q?=20libicu=EF=BC=89=EF=BC=8C=E6=94=B9=E7=94=A8=E5=AE=98=E6=96=B9?= =?UTF-8?q?=20bun=20=E7=BC=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- .gitea/workflows/deploy.yml | 44 ++++++++++++++++++++++++++++++------- docs/deploy.md | 10 ++++++--- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index add2d33..e8442b9 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -58,21 +58,49 @@ jobs: git clean -ffdxq -e node_modules git log --oneline -1 - # 单二进制把运行时一起打进去:开发机的 bun 是几,线上跑的就是几。 - # 开发机的 bun 是 pacman 装的,会跟着系统升级走,对不上就别部署。 - - name: 核对 bun 版本 + # 单二进制把运行时一起打进去:这里用的 bun 是哪个,线上跑的就是哪个。 + # + # ⚠️ **不能用开发机 PATH 里的 bun。** pacman 装的 bun 是 Arch 自己编的,动态链接系统的 + # ICU(libicui18n.so.78),编出来的 oj2-api 到容器里就报找不到这个库 —— 2026-11-03 + # 第一次跑就撞上了,好在迁移那步先炸、容器没动。官方发布的 bun 自带 ICU, + # 只依赖 libc,和 GitHub 上 setup-bun 装的是同一个东西。 + # + # 所以这里按 packageManager 的版本下载官方二进制(核 sha256),缓存在 + # ~/.cache/oj2-deploy/ 下,同一个版本只下一次;再把它放到 PATH 最前面, + # 后面的 bun install / bunx 都走它。 + - name: 装 bun run: | - want=$(sed -nE 's/.*"packageManager": *"bun@([^"]+)".*/\1/p' package.json) - have=$(bun --version) - echo "package.json 要 $want,本机是 $have" - [ "$want" = "$have" ] || { echo "::error::bun 版本对不上:要么把本机的 bun 换成 $want,要么照 CLAUDE.md 升级 packageManager 那三处"; exit 1; } + ver=$(sed -nE 's/.*"packageManager": *"bun@([^"]+)".*/\1/p' package.json) + [ -n "$ver" ] || { echo "::error::package.json 里读不到 packageManager 的 bun 版本"; exit 1; } + dir="$HOME/.cache/oj2-deploy/bun-v$ver" + if [ ! -x "$dir/bun" ]; then + tmp=$(mktemp -d) + base="https://github.com/oven-sh/bun/releases/download/bun-v$ver" + curl -fsSL --retry 3 -o "$tmp/bun-linux-x64.zip" "$base/bun-linux-x64.zip" + curl -fsSL --retry 3 -o "$tmp/SHASUMS256.txt" "$base/SHASUMS256.txt" + (cd "$tmp" && grep ' bun-linux-x64.zip$' SHASUMS256.txt | sha256sum -c -) + unzip -q "$tmp/bun-linux-x64.zip" -d "$tmp" + mkdir -p "$dir" + install -m755 "$tmp/bun-linux-x64/bun" "$dir/bun" + rm -rf "$tmp" + fi + [ "$("$dir/bun" --version)" = "$ver" ] || { echo "::error::$dir/bun 的版本不是 $ver"; exit 1; } + echo "$dir" >> "$GITHUB_PATH" + echo "用 $dir/bun($ver)" - name: 装依赖 run: bun install --frozen-lockfile # 输出到 dist/oj2-api,正是 Dockerfile 里 artifacts-prebuilt 阶段要的位置。 + # 编完先看它链接了什么:官方 bun 编出来的只依赖 libc 那几个,多出任何一个库 + # (比如 libicu)都说明用错了 bun,到容器里一定起不来。在这里拦下, + # 别等服务器上构建完镜像、迁移时才炸 —— 那时 oj2-api:latest 已经被换成坏镜像了。 - name: 编后端 - run: bun run --filter '@oj2/api' build + run: | + bun run --filter '@oj2/api' build + ldd dist/oj2-api + extra=$(ldd dist/oj2-api | awk '{print $1}' | grep -vE '^(linux-vdso\.so\.1|libc\.so\.6|libpthread\.so\.0|libdl\.so\.2|libm\.so\.6|/lib64/ld-linux-x86-64\.so\.2)$' || true) + [ -z "$extra" ] || { echo "::error::dist/oj2-api 多链接了这些库,容器里没有:$extra"; exit 1; } # 默认 production 模式,读 apps/web/.env.production(在版本库里)。 - name: 编前端 diff --git a/docs/deploy.md b/docs/deploy.md index 9396418..362a004 100644 --- a/docs/deploy.md +++ b/docs/deploy.md @@ -66,7 +66,8 @@ docker exec -it oj-postgres psql -U onlinejudge -d postgres -c '\password online git push origin main # 进度在 git.xuyue.cc/xuyue/OJ2/actions ``` -**push 时开发机得开着。** 没开的话任务在 Gitea 里排队,开机后 runner 连上就接着跑。 +**push 时开发机得开着。** 没开的话任务在 Gitea 里排队,开机后 runner 连上就接着跑; +排队超过 24 小时会被 Gitea 作废(`ABANDONED_JOB_TIMEOUT` 的默认值),那就要在 Actions 页面重跑。 为什么在开发机上编、不在服务器或 GitHub 上编: @@ -99,8 +100,11 @@ Run workflow),开发机不在、又急着上线时用。它不再 push 就 | 注册 | 同目录的 `.runner`;只给 `xuyue/OJ2` 这一个仓库用 | | 日志 | `journalctl --user -u gitea-runner -f`;每次部署的日志在 Gitea 的 Actions 页面 | -**bun 版本要对得上**:开发机的 bun 是 pacman 装的,会跟着系统升级走;单二进制会把运行时 -打进去,所以工作流第一步就核对 `bun --version` 和 `packageManager`,对不上直接判红。 +**部署不用开发机自己的 bun。** pacman 装的 bun 是 Arch 自己编的,动态链接系统 ICU,单二进制 +把它打进去之后到容器里报 `libicui18n.so.78: cannot open shared object file`(2026-11-03 第一次跑 +就撞上了,迁移那步先炸、容器没动)。工作流按 `packageManager` 的版本下载官方二进制、核 sha256, +缓存在 `~/.cache/oj2-deploy/bun-v<版本>/`;编完后端还会 `ldd` 一下,多链接了 libc 以外的库就判红。 +升级 bun 时这里不用管,改了 `packageManager` 下一次部署会自己下新版本。 换一台机器跑 runner:装 `gitea-runner`,在服务器上生成注册令牌,再照上面那份配置注册: