Compare commits

..

No commits in common. "main" and "test-4" have entirely different histories.
main ... test-4

View File

@ -18,8 +18,64 @@ env:
RELEASES_INDEX_URL: https://dotnetcli.azureedge.net/dotnet/release-metadata/releases-index.json RELEASES_INDEX_URL: https://dotnetcli.azureedge.net/dotnet/release-metadata/releases-index.json
jobs: jobs:
discover:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.discover.outputs.matrix }}
lts_major: ${{ steps.discover.outputs.lts_major }}
sts_major: ${{ steps.discover.outputs.sts_major }}
tag_suffix: ${{ steps.suffix.outputs.tag_suffix }}
steps:
- name: Determine tag suffix
id: suffix
run: |
if [[ "${{ github.event.release.prerelease }}" == "true" ]]; then
echo "tag_suffix=-test" >> $GITHUB_OUTPUT
echo "Prerelease detected — tags will use -test suffix"
else
echo "tag_suffix=" >> $GITHUB_OUTPUT
fi
- name: Discover supported .NET versions
id: discover
run: |
set -euo pipefail
RELEASES=$(curl -fsSL "$RELEASES_INDEX_URL")
# Filter active/go-live versions (excludes EOL automatically)
SUPPORTED=$(echo "$RELEASES" | jq -c '[.["releases-index"][] | select(.["support-phase"] == "active" or .["support-phase"] == "go-live")]')
# Build matrix JSON
MATRIX=$(echo "$SUPPORTED" | jq -c '{include: [.[] | {
major: (.["channel-version"] | split(".")[0]),
runtime: .["latest-runtime"],
sdk: .["latest-sdk"],
type: .["release-type"]
}]}')
# Find highest LTS and STS majors
LTS_MAJOR=$(echo "$SUPPORTED" | jq -r '[.[] | select(.["release-type"] == "lts")] | sort_by(.["channel-version"] | split(".") | map(tonumber)) | last | .["channel-version"] | split(".")[0]')
STS_MAJOR=$(echo "$SUPPORTED" | jq -r '[.[] | select(.["release-type"] == "sts")] | sort_by(.["channel-version"] | split(".") | map(tonumber)) | last | .["channel-version"] | split(".")[0] // ""')
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
echo "lts_major=$LTS_MAJOR" >> $GITHUB_OUTPUT
echo "sts_major=$STS_MAJOR" >> $GITHUB_OUTPUT
echo "Matrix: $MATRIX"
echo "LTS major: $LTS_MAJOR"
echo "STS major: $STS_MAJOR"
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: discover
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.discover.outputs.matrix) }}
env:
LTS_MAJOR: ${{ needs.discover.outputs.lts_major }}
STS_MAJOR: ${{ needs.discover.outputs.sts_major }}
TAG_SUFFIX: ${{ needs.discover.outputs.tag_suffix }}
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -43,36 +99,10 @@ jobs:
curl -fsSL https://github.com/chainguard-dev/apko/releases/latest/download/apko_$(curl -fsSL https://api.github.com/repos/chainguard-dev/apko/releases/latest | jq -r .tag_name | sed 's/^v//')_linux_amd64.tar.gz \ curl -fsSL https://github.com/chainguard-dev/apko/releases/latest/download/apko_$(curl -fsSL https://api.github.com/repos/chainguard-dev/apko/releases/latest | jq -r .tag_name | sed 's/^v//')_linux_amd64.tar.gz \
| tar xz --strip-components=1 -C /usr/local/bin | tar xz --strip-components=1 -C /usr/local/bin
- name: Install Docker Scout - name: Build apko base images
run: |
curl -fsSL https://raw.githubusercontent.com/docker/scout-cli/main/install.sh -o install-scout.sh
sh install-scout.sh
- name: Determine tag suffix
id: suffix
run: |
if [[ "${{ github.event.release.prerelease }}" == "true" ]]; then
echo "TAG_SUFFIX=-test" >> $GITHUB_ENV
echo "Prerelease detected — tags will use -test suffix"
else
echo "TAG_SUFFIX=" >> $GITHUB_ENV
fi
- name: Discover versions and build all images
run: | run: |
set -euo pipefail set -euo pipefail
# Discover supported .NET versions
RELEASES=$(curl -fsSL "$RELEASES_INDEX_URL")
SUPPORTED=$(echo "$RELEASES" | jq -c '[.["releases-index"][] | select(.["support-phase"] == "active" or .["support-phase"] == "go-live")]')
LTS_MAJOR=$(echo "$SUPPORTED" | jq -r '[.[] | select(.["release-type"] == "lts")] | sort_by(.["channel-version"] | split(".") | map(tonumber)) | last | .["channel-version"] | split(".")[0]')
STS_MAJOR=$(echo "$SUPPORTED" | jq -r '[.[] | select(.["release-type"] == "sts")] | sort_by(.["channel-version"] | split(".") | map(tonumber)) | last | .["channel-version"] | split(".")[0] // ""')
echo "LTS major: $LTS_MAJOR"
echo "STS major: $STS_MAJOR"
# Build apko base images (shared across all .NET versions)
for VARIANT in runtime runtime-invariant sdk; do for VARIANT in runtime runtime-invariant sdk; do
for ARCH in x86_64 aarch64; do for ARCH in x86_64 aarch64; do
echo "::group::Building apko base: $VARIANT ($ARCH)" echo "::group::Building apko base: $VARIANT ($ARCH)"
@ -83,88 +113,147 @@ jobs:
done done
done done
# Iterate over each supported .NET version - name: Download .NET binaries
echo "$SUPPORTED" | jq -r '.[] | "\(.["channel-version"] | split(".")[0]) \(.["latest-runtime"]) \(.["latest-sdk"]) \(.["release-type"])"' | \ run: |
while read -r MAJOR RUNTIME SDK TYPE; do set -euo pipefail
echo "============================================="
echo "Building .NET $MAJOR: runtime=$RUNTIME sdk=$SDK type=$TYPE"
echo "============================================="
# Download .NET binaries RUNTIME_VERSION="${{ matrix.runtime }}"
for ARCH in x86_64 aarch64; do SDK_VERSION="${{ matrix.sdk }}"
if [ "$ARCH" = "x86_64" ]; then
DOTNET_ARCH="x64"
PLATFORM_ARCH="amd64"
else
DOTNET_ARCH="arm64"
PLATFORM_ARCH="arm64"
fi
echo "::group::Downloading ASP.NET Core runtime $RUNTIME ($DOTNET_ARCH)" for ARCH in x86_64 aarch64; do
mkdir -p dotnet-${PLATFORM_ARCH}/runtime if [ "$ARCH" = "x86_64" ]; then
curl -fsSL "https://dotnetcli.azureedge.net/dotnet/aspnetcore/Runtime/${RUNTIME}/aspnetcore-runtime-${RUNTIME}-linux-${DOTNET_ARCH}.tar.gz" \ DOTNET_ARCH="x64"
-o /tmp/aspnet-runtime-${PLATFORM_ARCH}.tar.gz PLATFORM_ARCH="amd64"
tar xf /tmp/aspnet-runtime-${PLATFORM_ARCH}.tar.gz -C dotnet-${PLATFORM_ARCH}/runtime else
echo "::endgroup::" DOTNET_ARCH="arm64"
PLATFORM_ARCH="arm64"
fi
echo "::group::Downloading .NET SDK $SDK ($DOTNET_ARCH)" # Download ASP.NET Core runtime (for runtime and runtime-invariant)
mkdir -p dotnet-${PLATFORM_ARCH}/sdk echo "::group::Downloading ASP.NET Core runtime $RUNTIME_VERSION ($DOTNET_ARCH)"
curl -fsSL "https://dotnetcli.azureedge.net/dotnet/Sdk/${SDK}/dotnet-sdk-${SDK}-linux-${DOTNET_ARCH}.tar.gz" \ mkdir -p dotnet-${PLATFORM_ARCH}/runtime
-o /tmp/dotnet-sdk-${PLATFORM_ARCH}.tar.gz curl -fsSL "https://dotnetcli.azureedge.net/dotnet/aspnetcore/Runtime/${RUNTIME_VERSION}/aspnetcore-runtime-${RUNTIME_VERSION}-linux-${DOTNET_ARCH}.tar.gz" \
tar xf /tmp/dotnet-sdk-${PLATFORM_ARCH}.tar.gz -C dotnet-${PLATFORM_ARCH}/sdk -o /tmp/aspnet-runtime-${PLATFORM_ARCH}.tar.gz
echo "::endgroup::" tar xf /tmp/aspnet-runtime-${PLATFORM_ARCH}.tar.gz -C dotnet-${PLATFORM_ARCH}/runtime
done echo "::endgroup::"
# Build and push each variant # Download .NET SDK
for VARIANT in runtime runtime-invariant sdk; do echo "::group::Downloading .NET SDK $SDK_VERSION ($DOTNET_ARCH)"
if [ "$VARIANT" = "sdk" ]; then mkdir -p dotnet-${PLATFORM_ARCH}/sdk
VERSION="$SDK" curl -fsSL "https://dotnetcli.azureedge.net/dotnet/Sdk/${SDK_VERSION}/dotnet-sdk-${SDK_VERSION}-linux-${DOTNET_ARCH}.tar.gz" \
DOTNET_DIR="sdk" -o /tmp/dotnet-sdk-${PLATFORM_ARCH}.tar.gz
else tar xf /tmp/dotnet-sdk-${PLATFORM_ARCH}.tar.gz -C dotnet-${PLATFORM_ARCH}/sdk
VERSION="$RUNTIME" echo "::endgroup::"
DOTNET_DIR="runtime" done
fi
- name: Build and push runtime image
echo "::group::Building $VARIANT-$MAJOR" run: |
set -euo pipefail
# Prepare build context
CONTEXT="context-${VARIANT}-${MAJOR}" MAJOR="${{ matrix.major }}"
rm -rf "$CONTEXT" VERSION="${{ matrix.runtime }}"
mkdir -p "$CONTEXT" VARIANT="runtime"
for ARCH in amd64 arm64; do
APKO_ARCH=$([[ "$ARCH" == "amd64" ]] && echo "x86_64" || echo "aarch64") # Prepare build context
mkdir -p "$CONTEXT/build-${ARCH}/${VARIANT}" mkdir -p context-runtime
cp "build-${APKO_ARCH}/${VARIANT}/rootfs.tar.gz" "$CONTEXT/build-${ARCH}/${VARIANT}/" for ARCH in amd64 arm64; do
mkdir -p "$CONTEXT/dotnet-${ARCH}" APKO_ARCH=$([[ "$ARCH" == "amd64" ]] && echo "x86_64" || echo "aarch64")
cp -r "dotnet-${ARCH}/${DOTNET_DIR}" "$CONTEXT/dotnet-${ARCH}/" mkdir -p context-runtime/build-${ARCH}/runtime
done cp build-${APKO_ARCH}/${VARIANT}/rootfs.tar.gz context-runtime/build-${ARCH}/runtime/
cp "dockerfiles/${VARIANT}.Dockerfile" "$CONTEXT/Dockerfile" mkdir -p context-runtime/dotnet-${ARCH}
cp -r dotnet-${ARCH}/runtime context-runtime/dotnet-${ARCH}/
# Determine tags done
TAGS="-t $DOCKER_IMAGE:${VARIANT}-${MAJOR}${TAG_SUFFIX} -t $DOCKER_IMAGE:${VARIANT}-${VERSION}${TAG_SUFFIX}" cp dockerfiles/runtime.Dockerfile context-runtime/Dockerfile
if [ "$MAJOR" = "$LTS_MAJOR" ]; then
TAGS="$TAGS -t $DOCKER_IMAGE:${VARIANT}-lts${TAG_SUFFIX}" # Determine tags
fi TAGS="-t $DOCKER_IMAGE:${VARIANT}-${MAJOR}${TAG_SUFFIX} -t $DOCKER_IMAGE:${VARIANT}-${VERSION}${TAG_SUFFIX}"
if [ "$MAJOR" = "$STS_MAJOR" ]; then if [ "$MAJOR" = "$LTS_MAJOR" ]; then
TAGS="$TAGS -t $DOCKER_IMAGE:${VARIANT}-sts${TAG_SUFFIX}" TAGS="$TAGS -t $DOCKER_IMAGE:${VARIANT}-lts${TAG_SUFFIX}"
fi fi
if [ "$MAJOR" = "$STS_MAJOR" ]; then
echo "Building $VARIANT with tags: $TAGS" TAGS="$TAGS -t $DOCKER_IMAGE:${VARIANT}-sts${TAG_SUFFIX}"
docker buildx build --platform linux/amd64,linux/arm64 --push \ fi
--sbom=true --provenance=mode=max \
$TAGS \ echo "Building $VARIANT with tags: $TAGS"
"$CONTEXT/" docker buildx build --platform linux/amd64,linux/arm64 --push \
--sbom=true --provenance=mode=max \
echo "::endgroup::" $TAGS \
done context-runtime/
# Docker Scout CVE scan - name: Build and push runtime-invariant image
for VARIANT in runtime runtime-invariant sdk; do run: |
echo "::group::Scout scan: ${VARIANT}-${MAJOR}" set -euo pipefail
docker scout cves "$DOCKER_IMAGE:${VARIANT}-${MAJOR}${TAG_SUFFIX}" --only-severity critical,high || true
echo "::endgroup::" MAJOR="${{ matrix.major }}"
done VERSION="${{ matrix.runtime }}"
VARIANT="runtime-invariant"
# Clean up .NET binaries for this version before next iteration
rm -rf dotnet-amd64 dotnet-arm64 mkdir -p context-runtime-invariant
for ARCH in amd64 arm64; do
APKO_ARCH=$([[ "$ARCH" == "amd64" ]] && echo "x86_64" || echo "aarch64")
mkdir -p context-runtime-invariant/build-${ARCH}/runtime-invariant
cp build-${APKO_ARCH}/${VARIANT}/rootfs.tar.gz context-runtime-invariant/build-${ARCH}/runtime-invariant/
mkdir -p context-runtime-invariant/dotnet-${ARCH}
cp -r dotnet-${ARCH}/runtime context-runtime-invariant/dotnet-${ARCH}/
done
cp dockerfiles/runtime-invariant.Dockerfile context-runtime-invariant/Dockerfile
TAGS="-t $DOCKER_IMAGE:${VARIANT}-${MAJOR}${TAG_SUFFIX} -t $DOCKER_IMAGE:${VARIANT}-${VERSION}${TAG_SUFFIX}"
if [ "$MAJOR" = "$LTS_MAJOR" ]; then
TAGS="$TAGS -t $DOCKER_IMAGE:${VARIANT}-lts${TAG_SUFFIX}"
fi
if [ "$MAJOR" = "$STS_MAJOR" ]; then
TAGS="$TAGS -t $DOCKER_IMAGE:${VARIANT}-sts${TAG_SUFFIX}"
fi
echo "Building $VARIANT with tags: $TAGS"
docker buildx build --platform linux/amd64,linux/arm64 --push \
--sbom=true --provenance=mode=max \
$TAGS \
context-runtime-invariant/
- name: Build and push SDK image
run: |
set -euo pipefail
MAJOR="${{ matrix.major }}"
VERSION="${{ matrix.sdk }}"
VARIANT="sdk"
mkdir -p context-sdk
for ARCH in amd64 arm64; do
APKO_ARCH=$([[ "$ARCH" == "amd64" ]] && echo "x86_64" || echo "aarch64")
mkdir -p context-sdk/build-${ARCH}/sdk
cp build-${APKO_ARCH}/${VARIANT}/rootfs.tar.gz context-sdk/build-${ARCH}/sdk/
mkdir -p context-sdk/dotnet-${ARCH}
cp -r dotnet-${ARCH}/sdk context-sdk/dotnet-${ARCH}/
done
cp dockerfiles/sdk.Dockerfile context-sdk/Dockerfile
TAGS="-t $DOCKER_IMAGE:${VARIANT}-${MAJOR}${TAG_SUFFIX} -t $DOCKER_IMAGE:${VARIANT}-${VERSION}${TAG_SUFFIX}"
if [ "$MAJOR" = "$LTS_MAJOR" ]; then
TAGS="$TAGS -t $DOCKER_IMAGE:${VARIANT}-lts${TAG_SUFFIX}"
fi
if [ "$MAJOR" = "$STS_MAJOR" ]; then
TAGS="$TAGS -t $DOCKER_IMAGE:${VARIANT}-sts${TAG_SUFFIX}"
fi
echo "Building $VARIANT with tags: $TAGS"
docker buildx build --platform linux/amd64,linux/arm64 --push \
--sbom=true --provenance=mode=max \
$TAGS \
context-sdk/
- name: Install Docker Scout
run: |
curl -fsSL https://raw.githubusercontent.com/docker/scout-cli/main/install.sh -o install-scout.sh
sh install-scout.sh
- name: Docker Scout CVE Scan
run: |
MAJOR="${{ matrix.major }}"
for VARIANT in runtime runtime-invariant sdk; do
echo "::group::Scout scan: ${VARIANT}-${MAJOR}"
docker scout cves ${{ env.DOCKER_IMAGE }}:${VARIANT}-${MAJOR}${TAG_SUFFIX} --only-severity critical,high || true
echo "::endgroup::"
done done