ci: incremental backend tests, cached web dependencies, web build in parallel with the tests
This commit is contained in:
1 parent
006814823b
commit
be04045c8c
4 files changed
+119
-7
No files matched your search
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env bash
|
||||
# 后端测试,带增量编译:把后端源码同步到一个固定目录,在那里 dotnet build / test。
|
||||
#
|
||||
# 为什么:每条流水线的工作区都是新克隆的(路径、文件时间都是新的),MSBuild 没法增量,每次从零编译整个解决方案要两分钟。
|
||||
# 固定目录里 obj/bin 留着,同步时只更新内容真的变了的文件(按内容比较,没变的文件时间不动),MSBuild 就只重编译受影响的项目;
|
||||
# 改动小的时候整个测试 20–30 秒。
|
||||
#
|
||||
# 同一时间只允许一条流水线用这份缓存(flock);增量编译失败(缓存坏了)就清掉缓存从头编译一次,所以最坏也只是回到原来的速度。
|
||||
set -euo pipefail
|
||||
|
||||
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cache="${MOSHIRO_CI_CACHE:-/home/justme/woodpecker/cache/backend-tests}"
|
||||
src="$cache/src"
|
||||
mkdir -p "$cache"
|
||||
|
||||
# .NET 第一次运行的欢迎信息、遥测、开发证书,在每条流水线的临时 HOME 里都要白做一遍
|
||||
export DOTNET_CLI_TELEMETRY_OPTOUT=1 DOTNET_NOLOGO=1 DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 DOTNET_GENERATE_ASPNET_CERTIFICATE=false
|
||||
|
||||
exec 9> "$cache/.lock"
|
||||
flock -w 900 9 || { echo "could not get the backend test cache lock" >&2; exit 1; }
|
||||
|
||||
sync_sources() {
|
||||
mkdir -p "$src"
|
||||
local list
|
||||
list="$(mktemp)"
|
||||
# 构建要用的都在 backend/ 和根目录的几个文件里(Directory.Packages.props、global.json、NuGet 配置)
|
||||
(cd "$root" && git ls-files -z -- backend Directory.Packages.props global.json 'NuGet.*' 'nuget.*') | tr '\0' '\n' | sort -u > "$list"
|
||||
local changed=0 file
|
||||
while IFS= read -r file; do
|
||||
[[ -f "$root/$file" ]] || continue
|
||||
if ! cmp -s "$root/$file" "$src/$file" 2>/dev/null; then
|
||||
mkdir -p "$(dirname "$src/$file")"
|
||||
cp "$root/$file" "$src/$file"
|
||||
changed=$((changed + 1))
|
||||
fi
|
||||
done < "$list"
|
||||
# 仓库里已经删掉的文件,缓存里也要删(构建产物 artifacts 不动)
|
||||
local stale=0
|
||||
while IFS= read -r file; do
|
||||
[[ -n "$file" ]] || continue
|
||||
rm -f "$src/$file"
|
||||
stale=$((stale + 1))
|
||||
done < <(cd "$src" && find backend -type f -not -path 'backend/artifacts/*' -not -path '*/bin/*' -not -path '*/obj/*' 2>/dev/null | sort | comm -23 - <(grep '^backend/' "$list"))
|
||||
rm -f "$list"
|
||||
echo "synced sources: $changed changed, $stale removed"
|
||||
}
|
||||
|
||||
build() { (cd "$src/backend" && dotnet build MoShiro.slnx -c Release --nologo -v:q); }
|
||||
|
||||
sync_sources
|
||||
if ! build; then
|
||||
echo "incremental build failed; wiping the cache and building from scratch" >&2
|
||||
rm -rf "$src"
|
||||
sync_sources
|
||||
build
|
||||
fi
|
||||
|
||||
# 测试在缓存目录里跑完整的解决方案(不再重复编译)
|
||||
(cd "$src/backend" && dotnet test --solution MoShiro.slnx -c Release --no-build)
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/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"
|
||||
|
||||
key="$(cat "$web/package-lock.json" "$web/package.json" "$web/display/package.json" "$web/admin/package.json" | 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)
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
# 展示端和管理端并行构建,再检查 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; }
|
||||
npm run lint:css --prefix "$web"
|
||||
Reference in new issue
Block a user