#!/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)