Files
justme d1ece67a6a
ci/woodpecker/push/web-build Pipeline was successful
ci/woodpecker/push/verify Pipeline was canceled
ci/woodpecker/push/dev-image Pipeline was canceled
Build the frontend once per pipeline and reuse it in the dev backend image [CI]
2026-10-21 15:17:37 +08:00

63 lines
2.8 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 前端构建和 CSS 检查,带依赖缓存:node_modules 按「锁文件 + package.json」的哈希缓存起来,同样的依赖不再 npm ci(约 20 秒);
# 展示端和管理端并行构建。缓存里放的是硬链接副本(cp -al),恢复几乎是瞬间;依赖变了才重新安装并更新缓存,只留最近 3 份。
set -euo pipefail
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cache="${MOSHIRO_CI_CACHE:-/home/justme/woodpecker/cache/web-node-modules}"
export NPM_CONFIG_CACHE="${NPM_CONFIG_CACHE:-/home/justme/.npm}"
web="$root/web"
dirs=(node_modules display/node_modules admin/node_modules)
mkdir -p "$cache"
exec 9> "$cache/.lock"
# 开发构建会把版本号写进 package.json;缓存键里去掉 version 行,否则每个提交都是新的键,缓存永远命中不了
key="$(cat "$web/package-lock.json" "$web/package.json" "$web/display/package.json" "$web/admin/package.json" | grep -v '^ "version":' | sha256sum | cut -c1-16)"
restore() {
[[ -d "$cache/$key/node_modules" ]] || return 1
local d
for d in "${dirs[@]}"; do
[[ -d "$cache/$key/$d" ]] || continue
mkdir -p "$(dirname "$web/$d")"
cp -al "$cache/$key/$d" "$web/$d" 2>/dev/null || cp -a "$cache/$key/$d" "$web/$d"
done
}
save() {
local tmp="$cache/$key.tmp.$$" d
rm -rf "$tmp"
for d in "${dirs[@]}"; do
[[ -d "$web/$d" ]] || continue
mkdir -p "$(dirname "$tmp/$d")"
cp -al "$web/$d" "$tmp/$d" 2>/dev/null || cp -a "$web/$d" "$tmp/$d"
done
rm -rf "$cache/$key"
mv "$tmp" "$cache/$key"
# 只留最近用过的 3 份
(cd "$cache" && ls -1t | grep -v '\.tmp\.' | tail -n +4 | xargs -r rm -rf)
}
# 并行的 workflow(web-build 和开发镜像里的前端构建)会同时读写这份缓存:恢复和保存期间持锁
flock -w 600 9 || { echo "could not get the node_modules cache lock" >&2; exit 1; }
if restore; then
echo "restored node_modules from the cache ($key)"
else
echo "no cache for $key; running npm ci"
rm -rf "$web/node_modules" "$web/display/node_modules" "$web/admin/node_modules"
npm ci --prefix "$web" --prefer-offline
save || echo "could not save the node_modules cache" >&2
fi
flock -u 9
# 展示端和管理端并行构建,再检查 CSS
pids=()
(cd "$web" && timeout 600 npm run build -w display) & pids+=($!)
(cd "$web" && timeout 600 npm run build -w admin) & pids+=($!)
failed=0
for pid in "${pids[@]}"; do wait "$pid" || failed=1; done
[[ "$failed" == 0 ]] || { echo "web build failed" >&2; exit 1; }
[[ -n "${WEB_SKIP_LINT:-}" ]] || npm run lint:css --prefix "$web"
# 开发构建(main 上带 [CI] 的提交):前端是这条流水线的唯一一份,放进共享目录,开发镜像的 Backend 直接用(见 ci/shared-web.sh)
[[ -z "${WEB_PUBLISH_SHARED:-}" ]] || bash "$root/ci/shared-web.sh" publish