diff --git a/.woodpecker/dev-image.yml b/.woodpecker/dev-image.yml index 60bcc13..8dea49b 100644 --- a/.woodpecker/dev-image.yml +++ b/.woodpecker/dev-image.yml @@ -41,7 +41,6 @@ steps: - name: build-linux-amd64-agent image: bash environment: - NUGET_PACKAGES: /home/justme/.nuget/packages ZOT_REGISTRY: registry.oeo.one ZOT_USERNAME: justme ZOT_SECRET: @@ -56,7 +55,6 @@ steps: - name: build-linux-amd64-probe image: bash environment: - NUGET_PACKAGES: /home/justme/.nuget/packages ZOT_REGISTRY: registry.oeo.one ZOT_USERNAME: justme ZOT_SECRET: @@ -72,7 +70,6 @@ steps: - name: build-linux-arm64-agent image: bash environment: - NUGET_PACKAGES: /home/justme/.nuget/packages ZOT_REGISTRY: registry.oeo.one ZOT_USERNAME: justme ZOT_SECRET: @@ -87,7 +84,6 @@ steps: - name: build-linux-arm64-probe image: bash environment: - NUGET_PACKAGES: /home/justme/.nuget/packages ZOT_REGISTRY: registry.oeo.one ZOT_USERNAME: justme ZOT_SECRET: diff --git a/ci/build-dev-image.sh b/ci/build-dev-image.sh index 199be31..3050ace 100644 --- a/ci/build-dev-image.sh +++ b/ci/build-dev-image.sh @@ -102,12 +102,19 @@ context="$work/$component" local_image="localhost/moshiro-$component:dev-$arch-check" node_rid="linux-musl-x64" [[ "$arch" == arm64 ]] && node_rid="linux-musl-arm64" -# Keep writable NuGet caches isolated per parallel build (component + arch). -# Reuse still applies across pipeline runs without concurrent restore races. -# Keep the package cache across Buildah storage generations so refreshing a -# damaged layer store does not force another full NuGet download. -nuget_cache="/home/justme/woodpecker/buildah-home/dev-image-build-$component-$arch/nuget-packages" -mkdir -p "$nuget_cache" +# Build a dedicated .NET 10 NativeAOT/AotAnywhere environment in this isolated +# Buildah store. Keeping NuGet inside image layers avoids a shared writable +# package mount being corrupted by canceled or parallel builds. +builder_image="localhost/moshiro-dotnet10-nativeaot-aotanywhere:ci" +builder_context="$work/nativeaot-builder" +mkdir -p "$builder_context/backend" +install -m 0644 "$root/global.json" "$builder_context/global.json" +install -m 0644 "$root/Directory.Packages.props" "$builder_context/Directory.Packages.props" +install -m 0644 "$root/backend/Directory.Build.props" "$builder_context/backend/Directory.Build.props" +install -m 0644 "$root/backend/BannedSymbols.txt" "$builder_context/backend/BannedSymbols.txt" +run_bounded 30m buildah bud --layers --network host --tls-verify=true --arch amd64 \ + -f "$root/packaging/container/NativeAot.Builder.Containerfile" \ + -t "$builder_image" "$builder_context" # A stable timestamp lets a retry of the same commit reuse the publish layer. commit_epoch="$(git -C "$root" show -s --format=%ct "$CI_COMMIT_SHA")" @@ -115,7 +122,7 @@ built_at="$(date -u -d "@$commit_epoch" +%Y-%m-%dT%H:%M:%SZ)" python3 "$root/ci/stage-node-image.py" "$component" "$context" run_bounded 30m buildah bud --layers --network host --tls-verify=true --arch "$arch" \ - --volume "$nuget_cache:/root/.nuget/packages:rw" \ + --build-arg "NATIVEAOT_BUILDER_IMAGE=$builder_image" \ --build-arg "APP_VERSION=$image_version" \ --build-arg "NODE_RID=$node_rid" \ --build-arg "MOSHIRO_TAG=$MOSHIRO_TAG" --build-arg "MOSHIRO_COMMIT=${CI_COMMIT_SHA:0:10}" --build-arg "MOSHIRO_BUILT_AT=$built_at" \ diff --git a/packaging/container/Agent.NativeBuild.Containerfile b/packaging/container/Agent.NativeBuild.Containerfile index d803d27..70730a0 100644 --- a/packaging/container/Agent.NativeBuild.Containerfile +++ b/packaging/container/Agent.NativeBuild.Containerfile @@ -1,5 +1,7 @@ # Run all build commands on the native amd64 runner. AotAnywhere cross-links # the NativeAOT output, so an ARM64 build never needs QEMU. +ARG NATIVEAOT_BUILDER_IMAGE=localhost/moshiro-dotnet10-nativeaot-aotanywhere:ci + FROM --platform=linux/arm64 alpine:3.24 AS arm64-apk-keys FROM --platform=linux/amd64 alpine:3.24 AS runtime-libs @@ -19,7 +21,7 @@ RUN set -eu; \ for package do tar -xzf "$package" -C /tmp/runtime-root; done; \ cp -a /tmp/runtime-root/usr/lib/*.so* /out/runtime/ -FROM --platform=linux/amd64 mcr.microsoft.com/dotnet/sdk:10.0-noble-aot AS build +FROM --platform=linux/amd64 ${NATIVEAOT_BUILDER_IMAGE} AS build WORKDIR /src/backend COPY restore/backend/ ./ diff --git a/packaging/container/NativeAot.Builder.Containerfile b/packaging/container/NativeAot.Builder.Containerfile new file mode 100644 index 0000000..30a5d0d --- /dev/null +++ b/packaging/container/NativeAot.Builder.Containerfile @@ -0,0 +1,32 @@ +# Shared .NET 10 NativeAOT build environment for MoShiro's Linux node images. +# The SDK image includes the Linux NativeAOT compiler prerequisites. Warm the +# repository-pinned AotAnywhere MSBuild SDK into this image so builds do not +# depend on a writable host-mounted NuGet cache. +FROM --platform=linux/amd64 mcr.microsoft.com/dotnet/sdk:10.0-noble-aot + +ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 \ + DOTNET_NOLOGO=1 \ + NUGET_PACKAGES=/root/.nuget/packages + +WORKDIR /opt/aotanywhere +COPY global.json ./global.json +COPY Directory.Packages.props ./Directory.Packages.props +COPY backend/Directory.Build.props ./backend/Directory.Build.props +COPY backend/BannedSymbols.txt ./backend/BannedSymbols.txt + +WORKDIR /opt/aotanywhere/backend +RUN printf '%s\n' \ + '' \ + ' ' \ + ' ' \ + ' net10.0' \ + ' true' \ + ' true' \ + ' ' \ + '' > 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 \ + && rm Warmup.csproj \ + && rm -rf artifacts + +WORKDIR /src/backend diff --git a/packaging/container/Probe.NativeBuild.Containerfile b/packaging/container/Probe.NativeBuild.Containerfile index fcfe164..ac14461 100644 --- a/packaging/container/Probe.NativeBuild.Containerfile +++ b/packaging/container/Probe.NativeBuild.Containerfile @@ -1,5 +1,7 @@ # Run all build commands on the native amd64 runner. AotAnywhere cross-links # the NativeAOT output, so an ARM64 build never needs QEMU. +ARG NATIVEAOT_BUILDER_IMAGE=localhost/moshiro-dotnet10-nativeaot-aotanywhere:ci + FROM --platform=linux/arm64 alpine:3.24 AS arm64-apk-keys FROM --platform=linux/amd64 alpine:3.24 AS runtime-libs @@ -19,7 +21,7 @@ RUN set -eu; \ for package do tar -xzf "$package" -C /tmp/runtime-root; done; \ cp -a /tmp/runtime-root/usr/lib/*.so* /out/runtime/ -FROM --platform=linux/amd64 mcr.microsoft.com/dotnet/sdk:10.0-noble-aot AS build +FROM --platform=linux/amd64 ${NATIVEAOT_BUILDER_IMAGE} AS build WORKDIR /src/backend COPY restore/backend/ ./