docker-base-distro/.gitea/workflows/rebuild.yaml
Mathias Beaulieu-Duncan 4120f820a0
All checks were successful
Build and Push Base Distro Images / build-and-push (apko/base.yaml, base) (push) Successful in 10m9s
Build and Push Base Distro Images / build-and-push (apko/build.yaml, build) (push) Successful in 10m20s
Build and Push Base Distro Images / build-and-push (apko/dotnet-runtime.yaml, dotnet-runtime) (push) Successful in 10m10s
Build and Push Base Distro Images / build-and-push (apko/dotnet-sdk.yaml, dotnet-sdk) (push) Successful in 10m18s
Build and Push Base Distro Images / build-and-push (apko/flutter-sdk.yaml, flutter-sdk) (push) Successful in 10m5s
Weekly Rebuild (CVE Updates) / rebuild (apko/base.yaml, base) (push) Successful in 9m56s
Weekly Rebuild (CVE Updates) / rebuild (apko/build.yaml, build) (push) Successful in 9m59s
Weekly Rebuild (CVE Updates) / rebuild (apko/dotnet-runtime.yaml, dotnet-runtime) (push) Successful in 9m59s
Weekly Rebuild (CVE Updates) / rebuild (apko/dotnet-sdk.yaml, dotnet-sdk) (push) Successful in 10m1s
Weekly Rebuild (CVE Updates) / rebuild (apko/flutter-sdk.yaml, flutter-sdk) (push) Successful in 10m0s
Fix multi-arch builds to preserve OCI config metadata
Extract rootfs layer and config from apko OCI archive separately,
then generate Dockerfile with ENV, ENTRYPOINT, WORKDIR and USER
from the OCI config. Fixes missing environment variables in the
final multi-arch image.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 17:55:22 -05:00

179 lines
7.3 KiB
YAML

name: Weekly Rebuild (CVE Updates)
on:
schedule:
# Rebuild weekly to pick up Wolfi security patches
- cron: '0 6 * * 1'
push:
paths:
- '.gitea/workflows/rebuild.yaml'
permissions:
contents: read
env:
IMAGE_NAME: base-distro
APKO_VERSION: 1.1.2
jobs:
rebuild:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- config: apko/base.yaml
variant: base
- config: apko/build.yaml
variant: build
- config: apko/dotnet-runtime.yaml
variant: dotnet-runtime
- config: apko/dotnet-sdk.yaml
variant: dotnet-sdk
- config: apko/flutter-sdk.yaml
variant: flutter-sdk
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Install apko
run: |
APKO_ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
APKO_VER="${{ env.APKO_VERSION }}"
curl -fsSL "https://github.com/chainguard-dev/apko/releases/download/v${APKO_VER}/apko_${APKO_VER}_linux_${APKO_ARCH}.tar.gz" \
-o /tmp/apko.tar.gz
tar xzf /tmp/apko.tar.gz --strip-components=1 -C /usr/local/bin
rm /tmp/apko.tar.gz
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Registry
uses: docker/login-action@v3
with:
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Determine upstream version
id: version
run: |
VARIANT="${{ matrix.variant }}"
case "$VARIANT" in
base|build)
UPSTREAM=$(apko resolve ${{ matrix.config }} 2>&1 | grep -oP 'glibc-\K[0-9]+\.[0-9]+' | head -1 || echo "0.0")
if [ "$UPSTREAM" = "" ] || [ "$UPSTREAM" = "0.0" ]; then
UPSTREAM=$(apko resolve ${{ matrix.config }} 2>&1 | grep -oP 'glibc \(\K[0-9]+\.[0-9]+' | head -1 || echo "2.42")
fi
;;
dotnet-runtime)
UPSTREAM=$(curl -fsSL "https://dotnetcli.azureedge.net/dotnet/release-metadata/releases-index.json" \
| jq -r '[."releases-index"[] | select(."support-phase" == "active" or ."support-phase" == "go-live") | ."latest-runtime"] | sort_by(. | split(".") | map(tonumber)) | last')
;;
dotnet-sdk)
UPSTREAM=$(curl -fsSL "https://dotnetcli.azureedge.net/dotnet/release-metadata/releases-index.json" \
| jq -r '[."releases-index"[] | select(."support-phase" == "active" or ."support-phase" == "go-live") | ."latest-sdk"] | sort_by(. | split(".") | map(tonumber)) | last')
;;
flutter-sdk)
UPSTREAM=$(curl -fsSL "https://storage.googleapis.com/flutter_infra_release/releases/releases_linux.json" \
| jq -r '.current_release.stable as $hash | .releases[] | select(.hash == $hash and .channel == "stable") | .version')
;;
esac
echo "upstream=${UPSTREAM}" >> "$GITHUB_OUTPUT"
echo "Upstream version for ${VARIANT}: ${UPSTREAM}"
REPO_NAME="${{ env.IMAGE_NAME }}"
REGISTRY_URL="${{ secrets.REGISTRY_URL }}"
NAMESPACE=$(echo "$REGISTRY_URL" | sed 's|.*://||; s|.*\.io/||; s|/$||')
EXISTING_TAGS=$(curl -s "https://hub.docker.com/v2/repositories/${NAMESPACE}/${REPO_NAME}/tags?page_size=100&name=${VARIANT}-${UPSTREAM}." \
| jq -r '.results[]?.name // empty' 2>/dev/null || echo "")
MAX_BUILD=0
for tag in $EXISTING_TAGS; do
BUILD_NUM=$(echo "$tag" | grep -oP "\.\K[0-9]+$" || echo "0")
if [ "$BUILD_NUM" -gt "$MAX_BUILD" ] 2>/dev/null; then
MAX_BUILD=$BUILD_NUM
fi
done
NEXT_BUILD=$((MAX_BUILD + 1))
VERSION_TAG="${VARIANT}-${UPSTREAM}.${NEXT_BUILD}"
echo "version_tag=${VERSION_TAG}" >> "$GITHUB_OUTPUT"
echo "Next version tag: ${VERSION_TAG}"
- name: Build per-arch apko tarballs
run: |
mkdir -p /tmp/build-amd64 /tmp/build-arm64
apko build --arch x86_64 ${{ matrix.config }} \
${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest \
/tmp/build-amd64/image.tar
apko build --arch aarch64 ${{ matrix.config }} \
${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest \
/tmp/build-arm64/image.tar
# Extract the rootfs layer from the OCI archive for each arch.
# apko outputs an OCI image tarball; we need to extract just the
# filesystem layer (.tar.gz) and the config metadata.
for arch in amd64 arm64; do
cd /tmp/build-${arch}
tar xf image.tar
# The .tar.gz file is the filesystem layer
ROOTFS=$(ls *.tar.gz 2>/dev/null | head -1)
mv "$ROOTFS" rootfs.tar.gz
# Extract ENV and ENTRYPOINT from the OCI config
MANIFEST_DIGEST=$(jq -r '.manifests[0].digest' index.json | sed 's/sha256://')
CONFIG_DIGEST=$(jq -r '.config.digest' "sha256:${MANIFEST_DIGEST}" | sed 's/sha256://')
cp "sha256:${CONFIG_DIGEST}" config.json
# Clean up OCI artifacts
rm -f image.tar index.json manifest.json oci-layout sha256:*
cd /tmp
done
# Generate Dockerfile with metadata from the OCI config
# (use amd64 config as reference — env vars are the same for both arches)
ENV_LINES=$(jq -r '(.config.Env // [])[] | "ENV " + .' /tmp/build-amd64/config.json)
ENTRYPOINT=$(jq -r '(.config.Entrypoint // [])[]' /tmp/build-amd64/config.json | head -1)
USER_ID=$(jq -r '.config.User // "65532"' /tmp/build-amd64/config.json)
WORKDIR=$(jq -r '.config.WorkingDir // "/"' /tmp/build-amd64/config.json)
{
echo "FROM scratch"
echo "ARG TARGETARCH"
echo "ADD build-\${TARGETARCH}/rootfs.tar.gz /"
if [ -n "$ENV_LINES" ]; then
echo "$ENV_LINES"
fi
if [ -n "$ENTRYPOINT" ] && [ "$ENTRYPOINT" != "null" ]; then
echo "ENTRYPOINT [\"${ENTRYPOINT}\"]"
fi
echo "WORKDIR ${WORKDIR}"
echo "USER ${USER_ID}"
} > /tmp/Dockerfile
- name: Build and push with buildx (SBOM + provenance)
uses: docker/build-push-action@v5
with:
context: /tmp
file: /tmp/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
sbom: true
provenance: mode=max
tags: |
${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest
${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version_tag }}
- 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: |
docker pull ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest
docker scout cves ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ matrix.variant }}-latest --only-severity critical,high