docker-dotnet/.gitea/workflows/build.yaml
2026-02-03 15:23:21 -05:00

258 lines
9.9 KiB
YAML

name: Build and Push .NET Images
on:
release:
types: [published, prereleased]
workflow_dispatch:
schedule:
# Weekly rebuild for CVE patches (Sunday 6am UTC)
- cron: "0 6 * * 0"
permissions:
id-token: write
contents: read
packages: write
env:
DOCKER_IMAGE: docker.io/svrnty/dotnet
RELEASES_INDEX_URL: https://dotnetcli.azureedge.net/dotnet/release-metadata/releases-index.json
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:
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:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_SVRNTY_USERNAME }}
password: ${{ secrets.DOCKERHUB_SVRNTY_ACCESS_TOKEN }}
- name: Build apko base images
run: |
set -euo pipefail
for VARIANT in runtime runtime-invariant sdk; do
for ARCH in x86_64 aarch64; do
echo "::group::Building apko base: $VARIANT ($ARCH)"
mkdir -p ${{ github.workspace }}/build-${ARCH}/${VARIANT}
docker run --rm \
-v ${{ github.workspace }}/apko:/work:ro \
-v ${{ github.workspace }}/build-${ARCH}/${VARIANT}:/output \
cgr.dev/chainguard/apko build \
--arch $ARCH /work/${VARIANT}.yaml ${VARIANT}:latest /output/rootfs.tar.gz
echo "::endgroup::"
done
done
- name: Download .NET binaries
run: |
set -euo pipefail
RUNTIME_VERSION="${{ matrix.runtime }}"
SDK_VERSION="${{ matrix.sdk }}"
for ARCH in x86_64 aarch64; do
if [ "$ARCH" = "x86_64" ]; then
DOTNET_ARCH="x64"
PLATFORM_ARCH="amd64"
else
DOTNET_ARCH="arm64"
PLATFORM_ARCH="arm64"
fi
# Download ASP.NET Core runtime (for runtime and runtime-invariant)
echo "::group::Downloading ASP.NET Core runtime $RUNTIME_VERSION ($DOTNET_ARCH)"
mkdir -p dotnet-${PLATFORM_ARCH}/runtime
curl -fsSL "https://dotnetcli.azureedge.net/dotnet/aspnetcore/Runtime/${RUNTIME_VERSION}/aspnetcore-runtime-${RUNTIME_VERSION}-linux-${DOTNET_ARCH}.tar.gz" \
-o /tmp/aspnet-runtime-${PLATFORM_ARCH}.tar.gz
tar xf /tmp/aspnet-runtime-${PLATFORM_ARCH}.tar.gz -C dotnet-${PLATFORM_ARCH}/runtime
echo "::endgroup::"
# Download .NET SDK
echo "::group::Downloading .NET SDK $SDK_VERSION ($DOTNET_ARCH)"
mkdir -p dotnet-${PLATFORM_ARCH}/sdk
curl -fsSL "https://dotnetcli.azureedge.net/dotnet/Sdk/${SDK_VERSION}/dotnet-sdk-${SDK_VERSION}-linux-${DOTNET_ARCH}.tar.gz" \
-o /tmp/dotnet-sdk-${PLATFORM_ARCH}.tar.gz
tar xf /tmp/dotnet-sdk-${PLATFORM_ARCH}.tar.gz -C dotnet-${PLATFORM_ARCH}/sdk
echo "::endgroup::"
done
- name: Build and push runtime image
run: |
set -euo pipefail
MAJOR="${{ matrix.major }}"
VERSION="${{ matrix.runtime }}"
VARIANT="runtime"
# Prepare build context
mkdir -p context-runtime
for ARCH in amd64 arm64; do
APKO_ARCH=$([[ "$ARCH" == "amd64" ]] && echo "x86_64" || echo "aarch64")
mkdir -p context-runtime/build-${ARCH}/runtime
cp build-${APKO_ARCH}/${VARIANT}/rootfs.tar.gz context-runtime/build-${ARCH}/runtime/
mkdir -p context-runtime/dotnet-${ARCH}
cp -r dotnet-${ARCH}/runtime context-runtime/dotnet-${ARCH}/
done
cp dockerfiles/runtime.Dockerfile context-runtime/Dockerfile
# Determine tags
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/
- name: Build and push runtime-invariant image
run: |
set -euo pipefail
MAJOR="${{ matrix.major }}"
VERSION="${{ matrix.runtime }}"
VARIANT="runtime-invariant"
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