scripts: unify Linux native builds and retain restore caches [CI]
ci/woodpecker/push/dev-image Pipeline is running
ci/woodpecker/push/web-build Pipeline was successful
ci/woodpecker/push/verify Pipeline was successful

Build musl and glibc for amd64 and arm64 through one native package path. Reuse musl outputs for OCI images and OpenWrt installers, and export binaries inside a rootless unshare session.

Restore the executable dependency graph into a shared persistent NuGet cache, build managed dependencies once, and run isolated native publishes in parallel.

Clean temporary outputs and expired image layers under store locks, retire inactive legacy stores after seven days, and retain two toolchain exports. Add regression coverage for staging, extraction, packaging and cleanup boundaries.
This commit is contained in:
justme committed 2026-10-21 12:29:00 +08:00
1 parent 4515d7b075
commit 490b008a57
28 files changed
+712 -535

No files matched your search

+1 -2
View File
@@ -2,12 +2,11 @@ FROM mcr.microsoft.com/dotnet/runtime-deps:10.0-alpine
ARG APP_VERSION=unknown
LABEL org.opencontainers.image.title="MoShiro Agent" \
org.opencontainers.image.description="MoShiro node for Linux: listens and dials (MOSHIRO_MODE=agent) or only dials (MOSHIRO_MODE=dial)" \
org.opencontainers.image.description="MoShiro Agent for Linux: listens and dials" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.version="$APP_VERSION"
COPY --chown=1654:1654 app/moshiro-agent /usr/local/bin/moshiro-agent
COPY --chown=1654:1654 app/lib*.so.* /usr/local/bin/
COPY --chown=1654:1654 app/fleet-enroll /usr/local/bin/fleet-enroll
COPY --chown=1654:1654 config/ /etc/moshiro/
COPY --chown=1654:1654 --chmod=0755 entrypoint.sh /usr/local/bin/moshiro-entrypoint
@@ -1,59 +1,65 @@
# AotAnywhere cross-links both Alpine architectures on the native amd64 runner.
# Cross-compile Linux binaries on amd64; consumers package these outputs directly.
ARG NATIVEAOT_BUILDER_IMAGE=localhost/moshiro-dotnet10-nativeaot-aotanywhere:ci
FROM --platform=linux/amd64 ${NATIVEAOT_BUILDER_IMAGE} AS build
FROM --platform=linux/amd64 ${NATIVEAOT_BUILDER_IMAGE} AS toolchain
FROM toolchain AS restore
WORKDIR /src/backend
COPY restore/backend/ ./
ARG NODE_RID=linux-musl-x64
ARG STATIC_MSQUIC=true
ENV NUGET_PACKAGES=/root/.nuget/packages
RUN dotnet restore agent/src/MoShiro.Agent -r "$NODE_RID" -p:PublishAot=true -p:UseAotAnywhere=true \
-p:StaticMsQuic=true -p:StaticExecutable=true -p:RuntimeFrameworkVersion=10.0.12 \
-p:InvariantGlobalization=true --artifacts-path /artifacts \
&& dotnet restore fleet/tools/fleet-enroll -r "$NODE_RID" -p:PublishAot=true -p:UseAotAnywhere=true \
-p:StaticMsQuic=true -p:StaticExecutable=true -p:RuntimeFrameworkVersion=10.0.12 -p:InvariantGlobalization=true \
--artifacts-path /artifacts
# Layer hits skip restore. A dependency change still reuses downloaded packages.
# Seed an empty cache from the baked toolchain instead of downloading SDK/Zig again.
RUN --mount=type=cache,id=moshiro-nuget,target=/root/.nuget/packages,sharing=locked \
--mount=type=bind,from=toolchain,source=/root/.nuget/packages,target=/opt/nuget-seed,ro \
cp -a --update=none /opt/nuget-seed/. /root/.nuget/packages/ \
&& dotnet restore Agent.Native.proj -r "$NODE_RID" -p:PublishAot=true -p:UseAotAnywhere=true -p:SelfContained=true \
-p:StaticMsQuic="$STATIC_MSQUIC" -p:StaticExecutable="$STATIC_MSQUIC" \
-p:RuntimeFrameworkVersion=10.0.12 -p:InvariantGlobalization=true --artifacts-path /artifacts
FROM restore AS managed
COPY source/backend/ ./
COPY source/packaging/native/msquic/ /src/packaging/native/msquic/
# 构建信息:CI 通过 --build-arg 传入;不传就是空(放在 restore 之后,每次构建都变的时间不会让依赖还原的缓存失效)
ARG APP_VERSION=0.0.0-dev
ARG MOSHIRO_TAG=
ARG MOSHIRO_COMMIT=
ARG MOSHIRO_BUILT_AT=
ENV MOSHIRO_TAG=$MOSHIRO_TAG MOSHIRO_COMMIT=$MOSHIRO_COMMIT MOSHIRO_BUILT_AT=$MOSHIRO_BUILT_AT
RUN dotnet publish agent/src/MoShiro.Agent -m:3 -c Release -r "$NODE_RID" \
--self-contained true --no-restore -p:PublishAot=true -p:UseAotAnywhere=true \
-p:StaticMsQuic=true -p:StaticExecutable=true -p:RuntimeFrameworkVersion=10.0.12 \
-p:InvariantGlobalization=true -p:UseAppHost=true -p:StripSymbols=true \
-p:DebugType=none -p:DebugSymbols=false --artifacts-path /artifacts -o /out/agent \
&& dotnet publish fleet/tools/fleet-enroll -m:3 -c Release -r "$NODE_RID" \
--self-contained true --no-restore -p:PublishAot=true -p:UseAotAnywhere=true \
-p:StaticMsQuic=true -p:StaticExecutable=true -p:RuntimeFrameworkVersion=10.0.12 -p:InvariantGlobalization=true \
-p:UseAppHost=true -p:StripSymbols=true \
-p:DebugType=none -p:DebugSymbols=false --artifacts-path /artifacts -o /out/enroll \
&& rm -rf /artifacts
RUN test -x /out/agent/moshiro-agent && test -x /out/enroll/fleet-enroll \
# Build the project graph once; both native publishes reuse these managed outputs.
RUN --mount=type=cache,id=moshiro-nuget,target=/root/.nuget/packages,ro \
dotnet build Agent.Native.proj -m:3 -c Release -r "$NODE_RID" --no-restore \
-p:PublishAot=true -p:UseAotAnywhere=true -p:SelfContained=true -p:Version="$APP_VERSION" \
-p:StaticMsQuic="$STATIC_MSQUIC" -p:StaticExecutable="$STATIC_MSQUIC" \
-p:RuntimeFrameworkVersion=10.0.12 -p:InvariantGlobalization=true \
-p:UseAppHost=true -p:StripSymbols=true -p:DebugType=none -p:DebugSymbols=false --artifacts-path /artifacts
FROM managed AS build-agent
RUN --mount=type=cache,id=moshiro-nuget,target=/root/.nuget/packages,ro \
dotnet publish agent/src/MoShiro.Agent -m:3 -c Release -r "$NODE_RID" \
--self-contained true --no-build --no-restore -p:PublishAot=true -p:UseAotAnywhere=true \
-p:Version="$APP_VERSION" -p:StaticMsQuic="$STATIC_MSQUIC" -p:StaticExecutable="$STATIC_MSQUIC" \
-p:RuntimeFrameworkVersion=10.0.12 -p:InvariantGlobalization=true -p:UseAppHost=true -p:StripSymbols=true \
-p:DebugType=none -p:DebugSymbols=false --artifacts-path /artifacts -o /out/agent \
&& test -x /out/agent/moshiro-agent \
&& test "$(stat -c%s /out/agent/moshiro-agent)" -gt 2000000 \
&& if [ "$STATIC_MSQUIC" = true ]; then \
! readelf -l /out/agent/moshiro-agent | grep -q INTERP \
&& ! readelf -d /out/agent/moshiro-agent 2>&1 | grep -q NEEDED; \
fi
FROM managed AS build-enroll
RUN --mount=type=cache,id=moshiro-nuget,target=/root/.nuget/packages,ro \
dotnet publish fleet/tools/fleet-enroll -m:3 -c Release -r "$NODE_RID" \
--self-contained true --no-build --no-restore -p:PublishAot=true -p:UseAotAnywhere=true \
-p:Version="$APP_VERSION" -p:StaticMsQuic="$STATIC_MSQUIC" -p:StaticExecutable="$STATIC_MSQUIC" \
-p:RuntimeFrameworkVersion=10.0.12 -p:InvariantGlobalization=true -p:UseAppHost=true -p:StripSymbols=true \
-p:DebugType=none -p:DebugSymbols=false --artifacts-path /artifacts -o /out/enroll \
&& test -x /out/enroll/fleet-enroll \
&& test "$(stat -c%s /out/enroll/fleet-enroll)" -gt 2000000 \
&& ! readelf -l /out/agent/moshiro-agent | grep -q INTERP \
&& ! readelf -d /out/agent/moshiro-agent 2>&1 | grep -q NEEDED \
&& ! readelf -l /out/enroll/fleet-enroll | grep -q INTERP \
&& ! readelf -d /out/enroll/fleet-enroll 2>&1 | grep -q NEEDED
&& if [ "$STATIC_MSQUIC" = true ]; then \
! readelf -l /out/enroll/fleet-enroll | grep -q INTERP \
&& ! readelf -d /out/enroll/fleet-enroll 2>&1 | grep -q NEEDED; \
fi
FROM mcr.microsoft.com/dotnet/runtime-deps:10.0-alpine
ARG APP_VERSION=main
LABEL org.opencontainers.image.title="MoShiro Agent" \
org.opencontainers.image.description="MoShiro node agent for Linux" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.version="$APP_VERSION"
COPY --chown=1654:1654 --from=build /out/agent/moshiro-agent /usr/local/bin/moshiro-agent
COPY --chown=1654:1654 --from=build /out/enroll/fleet-enroll /usr/local/bin/fleet-enroll
COPY --chown=1654:1654 config/ /etc/moshiro/
COPY --chown=1654:1654 --chmod=0755 entrypoint.sh /usr/local/bin/moshiro-entrypoint
USER 1654:1654
WORKDIR /etc/moshiro
VOLUME ["/etc/moshiro"]
ENTRYPOINT ["/usr/local/bin/moshiro-entrypoint"]
CMD ["--config", "/etc/moshiro/agent.json"]
FROM scratch AS binaries
COPY --from=build-agent /out/agent/moshiro-agent /out/agent/moshiro-agent
COPY --from=build-enroll /out/enroll/fleet-enroll /out/enroll/fleet-enroll
@@ -28,10 +28,10 @@ RUN printf '%s\n' \
" <PackageReference Include=\"Vezel.Zig.Toolsets.linux-x64\" Version=\"$ZIG_TOOLSET_VERSION\" GeneratePathProperty=\"true\" />" \
' </ItemGroup>' \
'</Project>' > Warmup.csproj \
&& dotnet restore Warmup.csproj -p:PublishAot=true -p:UseAotAnywhere=true -r linux-musl-x64 \
&& dotnet restore Warmup.csproj -p:PublishAot=true -p:UseAotAnywhere=true -r linux-musl-arm64 \
&& dotnet restore Warmup.csproj -p:PublishAot=true -p:UseAotAnywhere=true -r linux-x64 \
&& dotnet restore Warmup.csproj -p:PublishAot=true -p:UseAotAnywhere=true -r linux-arm64 \
&& dotnet restore Warmup.csproj -p:RuntimeFrameworkVersion=10.0.12 -p:PublishAot=true -p:UseAotAnywhere=true -r linux-musl-x64 \
&& dotnet restore Warmup.csproj -p:RuntimeFrameworkVersion=10.0.12 -p:PublishAot=true -p:UseAotAnywhere=true -r linux-musl-arm64 \
&& dotnet restore Warmup.csproj -p:RuntimeFrameworkVersion=10.0.12 -p:PublishAot=true -p:UseAotAnywhere=true -r linux-x64 \
&& dotnet restore Warmup.csproj -p:RuntimeFrameworkVersion=10.0.12 -p:PublishAot=true -p:UseAotAnywhere=true -r linux-arm64 \
&& rm Warmup.csproj \
&& rm -rf bin obj